Kombinacje bez powtórzeń zbioru liczb – zapytanie SQL

Pytanie zgłoszone przez czytelnika. W jaki sposób z zestawu liczb będących w osobnych rekordach wyświetlić kombinacje bez powtórzeń. Dla przykładu wyświetlimy kombinacje bez powtórzeń zbioru 3 elementowego ze zbioru 6 elementowego. n!/k!(n-k)!

Tworzymy tabelę testową:

create table test(
id serial primary key,
  number float
);

insert into test(number) values(2.49);
insert into test(number) values(5.11);
insert into test(number) values(10);
insert into test(number) values(20);
insert into test(number) values(27.4);
insert into test(number) values(75);

W zapytaniu nasze dane złączamy 3 krotnie bo takiej wielkości zbiór unikalnych liczb chcemy uzyskać, złączamy z warunkiem na różne IDki aby uniknąć zduplikowanych liczb. Następnie w zapytaniu nadrzędnym odfiltrowujemy powtarzające się rekordy.

W przypadku gdybyśmy chcieli uzyskać zbiory 4 elementowe należy złączyć 4 krotnie, stworzyć kolumnę number4 i dodać na nią warunek w zapytaniu zewnętrznym.

SELECT 
*
FROM 
  (SELECT
    T1.number AS number1, 
    T2.number AS number2, 
    T3.number AS number3 
  FROM test AS T1 
  JOIN test AS T2 ON T1.id != T2.id
  JOIN test AS T3 ON T2.id != T3.id AND T1.id != T3.id
  ORDER BY number1, number2, number3
  ) AS sub
WHERE 
  sub.number1 <  sub.number2
AND
  sub.number2 <  sub.number3

Wynik zapytania:

 number1 | number2 | number3
---------+---------+---------
    2.49 |    5.11 |      10
    2.49 |    5.11 |      20
    2.49 |    5.11 |    27.4
    2.49 |    5.11 |      75
    2.49 |      10 |      20
    2.49 |      10 |    27.4
    2.49 |      10 |      75
    2.49 |      20 |    27.4
    2.49 |      20 |      75
    2.49 |    27.4 |      75
    5.11 |      10 |      20
    5.11 |      10 |    27.4
    5.11 |      10 |      75
    5.11 |      20 |    27.4
    5.11 |      20 |      75
    5.11 |    27.4 |      75
      10 |      20 |    27.4
      10 |      20 |      75
      10 |    27.4 |      75
      20 |    27.4 |      75
(20 rows)

Masz problem SQL do rozwiązania? Napisz.