我有很多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语句中执行此操作?
感谢。
答案 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;