How to make function in postgres that would take string or array and return all combinations of some length?
For example you have ABC and you want to get combinations with 2 characters, the result shoul be:
AB AC BC
Thank you in advance for your help.
with chars as (
select unnest(regexp_split_to_array('ABC','')) as c
)
select c1.c||c2.c
from chars c1
cross join chars c2
To remove permutations you can use the following:
with chars as (
select unnest(regexp_split_to_array('ABC','')) as c
)
select c1.c||c2.c
from chars c1
cross join chars c2
where c1.c < c2.c
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
;
Result:
str | str
-----+-----
W | T
W | F
W | !
T | F
T | !
F | !
(6 rows)
Unfortunately I cannot find a way to avoid the double string constant. (but the whole thing could be packed into a function) If there are no duplicate characters (or you want to suppres them) you could do the anti-join on the str instead of the idx.
UPDATE (hint from ypercube) It appears that the OP wants the strings to be concatenated. So be it::
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
;
Results:
results
---------
WT
WF
W!
TF
T!
F!
(6 rows)
UPDATE2: (here comes the recursive thingy...)
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
;
Results 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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With