来自单个 Table 的集合,按列分组

Sets From a Single Table, Grouped By a Column

我有一个table:

+-------+-------+----------+
| GROUP | State | Priority |
+-------+-------+----------+
|   1   |  MI   |     1    |
|   1   |  IA   |     2    |
|   1   |  CA   |     3    |
|   1   |  ND   |     4    |
|   1   |  AZ   |     5    |
|   2   |  IA   |     2    |
|   2   |  NJ   |     1    |
|   2   |  NH   |     3    |

And so on...

如何编写查询,按优先顺序按组对所有状态集进行查询?像这样:

+-------+--------------------+
| GROUP |        SET         |
+-------+--------------------+
|   1   | MI                 |
|   1   | MI, IA             |
|   1   | MI, IA, CA         |
|   1   | MI, IA, CA, ND     |
|   1   | MI, IA, CA, ND, AZ |
|   2   | NJ                 |
|   2   | NJ, IA             |
|   2   | NJ, IA, NH         |
+-------+--------------------+

这类似于我的问题,我试图修改该解决方案,但是,我只是一个 40 瓦的灯泡,而它是一个 60 瓦的问题...

这个问题实际上看起来比您链接的问题的答案更简单,这是解决该问题的绝佳方法。然而,这使用相同的分层查询,connect by

如果 priority 始终是连续的数字序列,这将起作用

SELECT t.grp, level, ltrim(SYS_CONNECT_BY_PATH(state,','),',')   as "set"  
   from  t 
   start with priority = 1
 connect by   priority = prior priority + 1
            and grp = prior grp

然而,如果这并不总是正确的,我们将需要row_number()根据优先级顺序定义序列(不需要是连续的整数)

with t2 AS
( 
  select t.*, row_number() 
        over ( partition by grp order by priority) as rn from t
)
SELECT t2.grp, ltrim(SYS_CONNECT_BY_PATH(state,','),',')   as "set"
   from  t2 
   start with priority = 1
 connect by   rn = prior rn + 1
            and grp = prior grp

DEMO

我知道这个问题已经得到解答,但我想看看我是否可以使用 ANSI 标准语法来做到这一点。 "connect by" 是 Oracle 独有的特性,以下将适用于多个数据库:

WITH
    -- ASET is just setting up the sample dataset
    aset AS
        (SELECT 1 AS grp, 'MI' AS state, 1 AS priority FROM DUAL
         UNION ALL
         SELECT 1 AS grp, 'IA', 2 FROM DUAL
         UNION ALL
         SELECT 1 AS grp, 'CA', 3 FROM DUAL
         UNION ALL
         SELECT 1 AS grp, 'ND', 4 FROM DUAL
         UNION ALL
         SELECT 1 AS grp, 'AZ', 5 FROM DUAL
         UNION ALL
         SELECT 2 AS grp, 'IA', 2 FROM DUAL
         UNION ALL
         SELECT 2 AS grp, 'NJ', 1 FROM DUAL
         UNION ALL
         SELECT 2 AS grp, 'NH', 3 FROM DUAL),
    bset AS
        -- In BSET we convert the ASET records into comma separated values
        (  SELECT grp, LISTAGG( state, ',' ) WITHIN GROUP (ORDER BY priority) AS set1
             FROM aset
         GROUP BY grp),
    cset ( grp
         , set1
         , set2
         , pos ) AS
        -- CSET breaks our comma separated values up into multiple rows
        -- Each row adding the next CSV value
        (SELECT grp                                                         AS grp
              , set1                                                        AS set1
              , SUBSTR( set1 || ',', 1, INSTR( set1 || ',', ',' ) - 1 )     AS set2
              , 1                                                           AS pos
           FROM bset
         UNION ALL
         SELECT grp              AS grp
              , set1             AS set1
              , SUBSTR( set1 || ','
                      , 1
                      ,   INSTR( set1 || ','
                               , ','
                               , 1
                               , pos + 1 )
                        - 1 )    AS set2
              , pos + 1          AS pos
           FROM cset
          WHERE INSTR( set1 || ','
                     , ','
                     , 1
                     , pos + 1 ) > 0)
  SELECT grp, set2
    FROM cset
ORDER BY grp, pos;