检索单行中的父母和子行

时间:2015-11-02 18:14:01

标签: sql oracle

我有很多SQL经验,但这个超出了我的理解。我有一张表如:

ID    NAME    PARENT_ID
1     A       0
2     B       1
3     C       1
4     D       0
5     E       4
6     F       4
7     G       4

我需要编写一个SQL语句,将所有父项及其子项返回一行:

ID    PARENT    CHILD_1     CHILD_2     CHILD_3  ...  CHILD_N
1     A         B           C
4     D         E           F           G

我不知道每个父母手头有多少孩子 - 它是可变的。

无论如何在单个SQL语句中执行此操作?

感谢。

1 个答案:

答案 0 :(得分:1)

你可以使用一些非常酷的"动态支点"那里有PL / SQL解决方案(根据我的经验,我不建议使用生产代码 - 它们可以工作99%,但对于一些奇怪的情况却失败了。)

否则,您需要提前告诉Oracle您希望SQL输出哪些列。这意味着,如果您对要包含的最大子列数实施硬性限制,则只能执行您要执行的操作。

如果你可以忍受不得不这样做,那么这应该有效。如果您的数据具有多个级别的层次结构,我会对您希望它如何工作进行一些猜测。 (看看样本数据中的行" H"并考虑如何显示它。)

WITH d AS ( 
SELECT 1 id, 'A' name, 0 parent_id
FROM DUAL UNION ALL
SELECT 2, 'B', 1
FROM DUAL UNION ALL
SELECT 3, 'C', 1
FROM DUAL UNION ALL
SELECT 4, 'D', 0
FROM DUAL UNION ALL
SELECT 5, 'E', 4
FROM DUAL UNION ALL
SELECT 6, 'F', 4
FROM DUAL UNION ALL
SELECT 7, 'G', 4
FROM DUAL UNION ALL
SELECT 8, 'H', 7

FROM DUAL
),
h as (
select prior d.name parent, 
       level lvl,
       case when level = 1 then null else d.name end child_name, 
       case when level = 1 then null else  row_number() over ( partition by prior d.name, level order by d.name) end child_Number
from d
connect by parent_id = prior id
start with parent_id = 0 )
select * from h
pivot ( max(child_name) for (child_number) in (1 AS "CHILD_1",2 AS "CHILD_2",3 AS "CHILD_3",4 AS "CHILD_4",5 AS "CHILD_5") )
where lvl > 1
order by parent;