set search_path='tmp';
WITH ztab AS (
SELECT idx as idx
, substring ( 'WTF!' FROM idx FOR 1) as str
FROM generate_series(1, char_length( 'WTF!' )) idx
)
SELECT t1.str, t2.str
FROM ztab t1
JOIN ztab t2 ON t2.idx > t1.idx
;
Resultado:
str | str
-----+-----
W | T
W | F
W | !
T | F
T | !
F | !
(6 rows)
Infelizmente, não consigo encontrar uma maneira de evitar a constante de string dupla. (mas a coisa toda pode ser empacotada em uma função) Se não houver caracteres duplicados (ou você quiser suprimi-los), você pode fazer o anti-join no str em vez do idx.
UPDATE (dica do ypercube) Parece que o OP deseja que as strings sejam concatenadas. Que assim seja::
WITH ztab AS (
SELECT idx as idx
, substring ( 'WTF!' FROM idx FOR 1) as str
FROM generate_series(1, char_length( 'WTF!' )) idx
)
SELECT t1.str || t2.str AS results
FROM ztab t1
JOIN ztab t2 ON t2.idx > t1.idx
;
Resultados:
results
---------
WT
WF
W!
TF
T!
F!
(6 rows)
UPDATE2:(aqui vem a coisa recursiva ...)
WITH RECURSIVE xtab AS (
WITH no_cte AS (
SELECT
1::int AS len
, idx as idx
, substring ( 'WTF!' FROM idx FOR 1) as str
FROM generate_series(1, char_length( 'WTF!' )) idx
)
SELECT t0.len as len
, t0.idx
, t0.str
FROM no_cte t0
UNION SELECT 1+t1.len
, tc.idx
, t1.str || tc.str AS str
FROM xtab t1
JOIN no_cte tc ON tc.idx > t1.idx
)
SELECT * FROM xtab
ORDER BY len, str
-- WHERE len=2
;
Resultados 3:
len | idx | str
-----+-----+------
1 | 4 | !
1 | 3 | F
1 | 2 | T
1 | 1 | W
2 | 4 | F!
2 | 4 | T!
2 | 3 | TF
2 | 4 | W!
2 | 3 | WF
2 | 2 | WT
3 | 4 | TF!
3 | 4 | WF!
3 | 4 | WT!
3 | 3 | WTF
4 | 4 | WTF!
(15 rows)