单个表格的组合,按列值分组

时间:2019-03-28 12:35:51

标签: sql oracle combinations

我有一个值表:

+-----+-------+
| ID  | STATE |
+-----+-------+
|  1  |   AL  |
|  1  |   AZ  |
|  1  |   MI  |
|  2  |   TX  |
|  2  |   TN  |
|  2  |   MO  |
|  2  |   ND  |
And many, many more...

如何编写一个查询,为每个ID生成所有可能的状态组合?结果如下:

+-----+-------------+
| ID  | COMBINATION |
+-----+-------------+
|  1  | AL, AZ      |
|  1  | AL, MI      |
|  1  | AZ, MI      |
|  1  | AL, AZ, MI  |
|  2  | TX, TN      |
|  2  | TX, MO      |
|  2  | TX, ND      |
|  2  | TN, MO      |
|  2  | TN, ND      |
  And so on...

感谢您的帮助!

编辑:Ravshan让我想到我不希望排列,但是如果组合字符串按字母顺序排列,则是奖励。

1 个答案:

答案 0 :(得分:2)

您可以使用分层查询来执行此操作-这是使用旧式connect by的查询:

WITH your_table AS (SELECT 1 ID, 'AL' state FROM dual UNION ALL
                    SELECT 1 ID, 'AZ' state FROM dual UNION ALL
                    SELECT 1 ID, 'MI' state FROM dual UNION ALL
                    SELECT 2 ID, 'TX' state FROM dual UNION ALL
                    SELECT 2 ID, 'TN' state FROM dual UNION ALL
                    SELECT 2 ID, 'MO' state FROM dual UNION ALL
                    SELECT 2 ID, 'ND' state FROM dual UNION ALL
                    SELECT 3 ID, 'OH' state FROM dual)
SELECT ID,
       state,
       ltrim(SYS_CONNECT_BY_PATH(state, ','), ',') combinations,
       LEVEL
FROM   (SELECT id,
               state,
               count(*) OVER (PARTITION BY id) state_cnt
        FROM your_table)
WHERE  state_cnt = 1
OR     (state_cnt > 1 AND LEVEL > 1)
CONNECT BY PRIOR ID = ID
           AND PRIOR state < state
           AND PRIOR sys_guid() IS NOT NULL;

        ID STATE COMBINATIONS      LEVEL
---------- ----- ------------ ----------
         1 AZ    AL,AZ                 2
         1 MI    AL,AZ,MI              3
         1 MI    AL,MI                 2
         1 MI    AZ,MI                 2
         2 TX    TN,TX                 2
         2 TX    MO,TX                 2
         2 TN    MO,TN                 2
         2 TX    MO,TN,TX              3
         2 ND    MO,ND                 2
         2 TX    MO,ND,TX              3
         2 TN    MO,ND,TN              3
         2 TX    MO,ND,TN,TX           4
         2 TX    ND,TX                 2
         2 TN    ND,TN                 2
         2 TX    ND,TN,TX              3
         3 OH    OH                    1

connect by子句中的prior sys_guid() is not null条件是必需的,以确保我们遍历正确的行(如果忽略它,结果将包含许多额外的行)。

我已经排除了输出中只有一个状态的行-除非id仅列出了一个状态。您可能会或可能不想在输出中包含单个状态,在这种情况下,可以完全删除谓词。