SQL и уникальные комбинации n-coulmn - PullRequest
7 голосов
/ 08 мая 2011

Существует ли в Oracle простой способ запрашивать уникальные комбинации из n полей.У меня очень простое решение с двумя полями:

CREATE TABLE combinations AS
SELECT 1 AS n 
  FROM DUAL
UNION ALL
SELECT 2
  FROM DUAL;

Запрос уникальных комбинаций:

SELECT LEAST(x.a, x.b), 
       GREATEST(x.a,x.b) 
  FROM (SELECT c1.n a, 
               c2.n b 
          FROM combinations c1
    CROSS JOIN combinations c2
         WHERE c1.n <> c2.n) x
GROUP BY LEAST(x.a, x.b), GREATEST(x.a,x.b);

Из этого запроса 1,2 и 2,1 считаются одинаковымиК сожалению, это не работает для структуры с 3 полями (например, 1,2,3 должно рассматриваться как 3,1,2, потому что порядок значений не имеет значения).Предоставляют ли аналитические функции Oracle подходящее решение для этого вопроса?Не могли бы вы предложить какую-то конкретную аналитическую функцию Oracle?

Ответы [ 2 ]

6 голосов
/ 08 мая 2011

Ваш запрос для 2 столбцов может быть переписан так:

SELECT
  c1.n,
  c2.n
FROM combinations c1
  INNER JOIN combinations c2 ON c1.n < c2.n

Для 3 столбцов вам потребуется внести некоторые дополнения (выделены жирным шрифтом):

SELECT
  c1.n,
  c2.n<b>,
  c3.n</b>
FROM combinations c1
  INNER JOIN combinations c2 ON c1.n < c2.n
  <b>INNER JOIN combinations c3 ON c2.n < c3.n</b>

Я уверен, что теперь вы можете легко догадаться, как масштабировать это для большего количества столбцов.

0 голосов
/ 08 мая 2011

Ваше решение заключается в использовании конвейерной табличной функции для возврата ваших комбинаций.

Ваша функция может находиться в своем собственном пакете (с состоянием пакета), который возвращает нужные вам данные в нужном вам порядке. Состояние должно быть набором переменных, определяемых числом возвращаемых столбцов, инициализированных начальными начальными значениями (A = 1, B = A + 1, C = B + 1, D = C + 1 и т. Д.). Тогда вы просто

PIPE ROW(a,b,c,d);
-- increment D
-- if D overflow limit, increment C and re-init D to C+1
-- if C overflow limit-1, increment B and re-init C to B+1
-- if B overflow limit-2, increment A and re-init B to A+1
-- if A overflow limit-3, the end

Это выходы, для N = 6

 1,2,3,4
 1,2,3,5
 1,2,3,6
 1,2,4,5
 1,2,4,6
 1,3,4,5
 1,3,4,6
 2,3,4,5
 2,3,4,6
 2,3,5,6
 3,4,5,6
...