如何通过主ID对查询中的行进行排序和分组

时间:2019-07-01 09:27:32

标签: sql oracle oracle11g

我正在尝试在Oracle中编写一个选择查询,其中结果按组“隔离”。每个组都有一个带有一些子级的父级实体,因此我想对行进行分组,使每个组均以父级实体开头,后跟相应的子级。

表具有以下结构:

ID | CREATION_DATE       | MASTER_ID
33 | 2019-07-01 09:31:04 | null
52 | 2019-07-01 10:45:04 | null
64 | 2019-07-01 11:00:04 | 33
71 | 2019-07-01 11:01:04 | 52
72 | 2019-07-01 12:31:04 | 33

到目前为止,我尝试了以下代码,这些代码返回未按MASTER_ID分组但在CREATION_DATE正确排序的行:

SELECT ID, CREATION_DATE, MASTER_ID
FROM ENTITY
WHERE CREATION_DATE >= TO_DATE('06-01-2019','MM-DD-YYYY')
ORDER BY CREATION_DATE DESC

我想找到一种返回以下结构的方法:

ID | CREATION_DATE       | MASTER_ID
33 | 2019-07-01 09:31:04 | null
64 | 2019-07-01 11:00:04 | 33
72 | 2019-07-01 12:31:04 | 33
52 | 2019-07-01 10:45:04 | null
71 | 2019-07-01 11:01:04 | 52

问题在于父实体一直都是null,所以我不能使用GROUP BY。 您对我应该如何处理有任何建议吗?

3 个答案:

答案 0 :(得分:0)

您可以通过使用connect by分层查询以及order siblings by子句来完成此操作,例如:

WITH your_table AS (SELECT 33 ID, to_date('2019-07-01 09:31:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, NULL master_id FROM dual UNION ALL
                    SELECT 52 ID, to_date('2019-07-01 10:45:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, NULL master_id FROM dual UNION ALL
                    SELECT 72 ID, to_date('2019-07-01 12:31:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, 33 master_id FROM dual UNION ALL
                    SELECT 64 ID, to_date('2019-07-01 11:00:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, 33 master_id FROM dual UNION ALL
                    SELECT 71 ID, to_date('2019-07-01 11:01:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, 52 master_id FROM dual)
SELECT ID,
       creation_date,
       master_id,
       connect_by_root(ID) top_id
FROM   your_table
START WITH master_id IS NULL
CONNECT BY PRIOR ID = master_id
ORDER SIBLINGS BY creation_date;

        ID CREATION_DATE  MASTER_ID     TOP_ID
---------- ------------- ---------- ----------
        33 01/07/2019 09                    33
        64 01/07/2019 11         33         33
        72 01/07/2019 12         33         33
        52 01/07/2019 10                    52
        71 01/07/2019 11         52         52

答案 1 :(得分:0)

我认为使用动态列进行排序很简单。

WITH your_table AS (SELECT 33 ID, to_date('2019-07-01 09:31:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, NULL master_id FROM dual UNION ALL
                    SELECT 52 ID, to_date('2019-07-01 10:45:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, NULL master_id FROM dual UNION ALL
                    SELECT 72 ID, to_date('2019-07-01 12:31:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, 33 master_id FROM dual UNION ALL
                    SELECT 64 ID, to_date('2019-07-01 11:00:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, 33 master_id FROM dual UNION ALL
                    SELECT 71 ID, to_date('2019-07-01 11:01:04', 'yyyy-mm-dd hh24:mi:ss') creation_date, 52 master_id FROM dual)
SELECT
    ID,
    CREATION_DATE,
    MASTER_ID
FROM
    (
        SELECT
            ID,
            CREATION_DATE,
            MASTER_ID,
            CASE
                WHEN MASTER_ID IS NULL THEN 0
                ELSE 1
            END AS RN
        FROM
            YOUR_TABLE
        ORDER BY
            CASE
                WHEN MASTER_ID IS NULL THEN ID
                ELSE MASTER_ID
            END,
            RN
    );

db<>fiddle demo

干杯!

答案 2 :(得分:0)

如果您只有一个层次结构,则只需执行以下操作:

select t.*
from t
order by coalesce(t.master_id, t.id),
         t.creation_date