2015-05-28 2 views
5

Ввод представляет собой массив длины «n». Мне нужно создать все возможные комбинации элементов массива, включая все комбинации с меньшим количеством элементов из входного массива.PostgreSQL находит все возможные комбинации (перестановки) в рекурсивном запросе

IN: j='{A, B, C ..}' 
OUT: k='{A, AB, AC, ABC, ACB, B, BA, BC, BAC, BCA..}' 

С повторами, так и с ABBA ..

Я пытался что-то вроде этого:

WITH RECURSIVE t(i) AS (SELECT * FROM unnest('{A,B,C}'::text[])) 
,cte AS (
    SELECT i AS combo, i, 1 AS ct 
    FROM t 
    UNION ALL 
    SELECT cte.combo || t.i, t.i, ct + 1 
    FROM cte 
    JOIN t ON t.i > cte.i 
) 
SELECT ARRAY(SELECT combo FROM cte ORDER BY ct, combo) AS result; 

Это порождает комбинации без повторений ... так что мне нужно изменить что-то ,

+4

Что вы пытаетесь? Вы должны сделать это в Postgres? Можете ли вы использовать PL/PGSQL или другой процедурный язык? Должны ли вы использовать массивы? –

+0

Вам нужны строки длиной от 1 до 3? – 1010

+0

Ввод является переменным, поэтому он должен составлять комбинации из всех элементов массива. – Adam

ответ

2

В рекурсивном запросе термины в таблице поиска, которые используются в итерации, удаляются, а затем запрос повторяется с остальными записями. В вашем случае это означает, что как только вы обработали первый элемент массива («A»), он больше не доступен для дальнейших перестановок элементов массива. Чтобы вернуть эти «использованные» элементы, вам нужно перекреститься с таблицей элементов массива в рекурсивном запросе, а затем отфильтровать элементы массива, уже используемые в текущей перестановке (position(t.i in cte.combo) = 0), и условие для остановки итераций (ct <= 3).

WITH RECURSIVE t(i) AS (
    SELECT * FROM unnest('{A,B,C}'::char[]) 
), cte AS (
    SELECT i AS combo, i, 1 AS ct 
    FROM t 
    UNION ALL 
    SELECT cte.combo || t.i, t.i, ct + 1 
    FROM cte, t 
    WHERE ct <= 3 
     AND position(t.i in cte.combo) = 0 
) 
SELECT ARRAY(SELECT combo FROM cte ORDER BY ct, combo) AS result; 
+0

Вот скрипт SQL: http://www.sqlfiddle.com/#!15/9eecb7db59d16c80417c72d1e1f4fbf1/ 497. –

+0

@Patrick Спасибо, человек! Ты просто сделал мой день .. :) спасатель .. спасибо .. – Adam