编写 SQL 查询以从 Table 中获取唯一的超级 Child 记录
Write a SQL query to get the only Super Child records from the Table
我正在努力准备一个 SQL 查询,该查询应该 return 一次性获得预期数据。
我的要求是从名为 JobCollection 的 SQl table 获取数据,这样 return 数据将作为在下图中以绿色边框突出显示。
此数据以 Parent Child 方式组织。
如下所示,
- JCId 1 是 JCId 3、4、5 的 ParentID。与 JCId 2 相同的是 JCId 6,7 的 ParentID。
- JCId 3,4,5 也是 ParentId 8,9,10,11,12 等等。
条件:
- 我只想从 JobCollection table 中获取那些 JCId 不是任何其他记录的 parent 的记录。
如绿色边框突出显示,JCId 8、9、10、11 和 12 不是任何记录的 parent
另外,绿色边框突出显示 JCId 1 的超级 child 而不是 JCId 2
请注意,这是一个示例,我们不能用于存储过程或游标。并且层次结构级别未定义。它可以是任何东西。
更新:
再举一个例子
我只想获取那些以红色突出显示的记录。如您所见,绿色边框表示这些是每条记录的超级 child,但红色突出显示 JCId 1
的超级 child 记录
From bottom of heart I request to everyone please read the question carefully and understand the pain in it before down voting to the question. It is really hard for me to get the expected result
方法有很多种。这里是 1.
select whatever
from table t1 left join table t2 on jcid = jcparentid
where t2.jcid is null
我试试看:
SELECT JcId FROM JobCollection
WHERE JcId NOT IN (SELECT JcParentId FROM JobCollection)
更新:Select 仅当 JcParentId = 1
SELECT JcId FROM JobCollection
WHERE JcId NOT IN (SELECT JcParentId FROM JobCollection)
AND JcParentId = 1
可能比您需要的多一点,但如果需要,您可以将其精简。
这里的技巧是使用范围键R1/R2。
Declare @YourTable table (JCId int,JCParentId int,JCName varchar(50))
Insert into @YourTable values
( 1, NULL,'A')
,( 2, NULL,'B')
,( 3, 1 ,'A1')
,( 4, 1 ,'A2')
,( 5, 1 ,'A3')
,( 6, 2 ,'B1')
,( 7, 2 ,'B2')
,( 8, 3 ,'A11')
,( 9, 3 ,'A12')
,(10, 4 ,'A21')
,(11, 5 ,'A31')
,(12, 5 ,'A32')
,(13, 6 ,'B11')
,(14, 6 ,'B12')
,(15, 7 ,'B21')
,(16, 7 ,'V22')
Declare @Top int = 1 --null --<< Sets top of Hier Try 3
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability
;with cteP as (
Select Seq = cast(10000+Row_Number() over (Order by JCName) as varchar(500))
,JCId
,JCParentId
,Lvl=1
,JCName
From @YourTable
Where IsNull(@Top,-1) = case when @Top is null then isnull(JCParentId ,-1) else JCId end
Union All
Select Seq = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.JCName)) as varchar(500))
,r.JCId
,r.JCParentId
,p.Lvl+1
,r.JCName
From @YourTable r
Join cteP p on r.JCParentId = p.JCId)
,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP)
,cteR2 as (Select A.JCId,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.JCId )
Select A.R1
,B.R2
,A.JCId
,A.JCParentId
,A.Lvl
,JCName = Replicate(@Nest,A.Lvl-1) + A.JCName
From cteR1 A
Join cteR2 B on A.JCId=B.JCId
and R1=R2
Returns
Full Hierarchy when @Top = NULL 并且删除最后一个和 R1=R2
使用递归 cte 获取一个 JCId
的所有后代,然后使用 not exists()
:
选择那些没有自己 children 的后代
declare @ParentId int;
set @ParentId = 1;
with cte as (
select JCId, JCName, JCParentId, JCParentName
from JobCollection
where JCId = @ParentId
union all
select c.JCId, c.JCName, c.JCParentId, c.JCParentName
from JobCollection c
inner join cte p on p.JCId = c.JCParentId
)
select JCId, JCName, JCParentId, JCParentName
from cte as o
where not exists (
select 1
from cte as i
where o.JCid = i.JCParentId
);
测试设置:http://rextester.com/LGEQD6195
create table JobCollection (
JCId int
, JCName varchar(50)
, JCParentId int
, JCParentName varchar(50)
);
insert into JobCollection values
( 1, 'A' , null, null)
,( 2, 'B' , null, null)
,( 3, 'A1' , 1, null)
,( 4, 'A2' , 1, null)
,( 5, 'A3' , 1, null)
,( 6, 'B1' , 2, null)
,( 7, 'B2' , 2, null)
,( 8, 'A11', 3, null)
,( 9, 'A12', 3, null)
,(10, 'A21', 4, null)
,(11, 'A31', 5, null)
,(12, 'A32', 5, null)
,(13, 'B11', 6, null)
,(14, 'B12', 6, null)
,(15, 'B21', 7, null)
,(16, 'B22', 7, null);
查询:
declare @ParentId int;
set @ParentId = 1;
with cte as (
select JCId, JCName, JCParentId, JCParentName
from JobCollection
where JCId = @ParentId
union all
select c.JCId, c.JCName, c.JCParentId, JCParentName = p.JCName
from JobCollection c
inner join cte p on p.JCId = c.JCParentId
)
select JCId, JCName, JCParentId, JCParentName
from cte as o
where not exists (
select 1
from cte as i
where o.JCid = i.JCParentId
);
结果:
+------+--------+------------+--------------+
| JCId | JCName | JCParentId | JCParentName |
+------+--------+------------+--------------+
| 11 | A31 | 5 | A3 |
| 12 | A32 | 5 | A3 |
| 10 | A21 | 4 | A2 |
| 8 | A11 | 3 | A1 |
| 9 | A12 | 3 | A1 |
+------+--------+------------+--------------+
这应该有效!
SELECT distinct J1.*
from JobCollection J1
LEFT JOIN JobCollection J2 ON J1.JCId = J2.JcParentId
WHERE J2.JcParentId IS NULL
我正在努力准备一个 SQL 查询,该查询应该 return 一次性获得预期数据。
我的要求是从名为 JobCollection 的 SQl table 获取数据,这样 return 数据将作为在下图中以绿色边框突出显示。
此数据以 Parent Child 方式组织。 如下所示,
- JCId 1 是 JCId 3、4、5 的 ParentID。与 JCId 2 相同的是 JCId 6,7 的 ParentID。
- JCId 3,4,5 也是 ParentId 8,9,10,11,12 等等。
条件:
- 我只想从 JobCollection table 中获取那些 JCId 不是任何其他记录的 parent 的记录。
如绿色边框突出显示,JCId 8、9、10、11 和 12 不是任何记录的 parent
另外,绿色边框突出显示 JCId 1 的超级 child 而不是 JCId 2
请注意,这是一个示例,我们不能用于存储过程或游标。并且层次结构级别未定义。它可以是任何东西。
更新:
再举一个例子
我只想获取那些以红色突出显示的记录。如您所见,绿色边框表示这些是每条记录的超级 child,但红色突出显示 JCId 1
的超级 child 记录From bottom of heart I request to everyone please read the question carefully and understand the pain in it before down voting to the question. It is really hard for me to get the expected result
方法有很多种。这里是 1.
select whatever
from table t1 left join table t2 on jcid = jcparentid
where t2.jcid is null
我试试看:
SELECT JcId FROM JobCollection
WHERE JcId NOT IN (SELECT JcParentId FROM JobCollection)
更新:Select 仅当 JcParentId = 1
SELECT JcId FROM JobCollection
WHERE JcId NOT IN (SELECT JcParentId FROM JobCollection)
AND JcParentId = 1
可能比您需要的多一点,但如果需要,您可以将其精简。
这里的技巧是使用范围键R1/R2。
Declare @YourTable table (JCId int,JCParentId int,JCName varchar(50))
Insert into @YourTable values
( 1, NULL,'A')
,( 2, NULL,'B')
,( 3, 1 ,'A1')
,( 4, 1 ,'A2')
,( 5, 1 ,'A3')
,( 6, 2 ,'B1')
,( 7, 2 ,'B2')
,( 8, 3 ,'A11')
,( 9, 3 ,'A12')
,(10, 4 ,'A21')
,(11, 5 ,'A31')
,(12, 5 ,'A32')
,(13, 6 ,'B11')
,(14, 6 ,'B12')
,(15, 7 ,'B21')
,(16, 7 ,'V22')
Declare @Top int = 1 --null --<< Sets top of Hier Try 3
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability
;with cteP as (
Select Seq = cast(10000+Row_Number() over (Order by JCName) as varchar(500))
,JCId
,JCParentId
,Lvl=1
,JCName
From @YourTable
Where IsNull(@Top,-1) = case when @Top is null then isnull(JCParentId ,-1) else JCId end
Union All
Select Seq = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.JCName)) as varchar(500))
,r.JCId
,r.JCParentId
,p.Lvl+1
,r.JCName
From @YourTable r
Join cteP p on r.JCParentId = p.JCId)
,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP)
,cteR2 as (Select A.JCId,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.JCId )
Select A.R1
,B.R2
,A.JCId
,A.JCParentId
,A.Lvl
,JCName = Replicate(@Nest,A.Lvl-1) + A.JCName
From cteR1 A
Join cteR2 B on A.JCId=B.JCId
and R1=R2
Returns
Full Hierarchy when @Top = NULL 并且删除最后一个和 R1=R2
使用递归 cte 获取一个 JCId
的所有后代,然后使用 not exists()
:
declare @ParentId int;
set @ParentId = 1;
with cte as (
select JCId, JCName, JCParentId, JCParentName
from JobCollection
where JCId = @ParentId
union all
select c.JCId, c.JCName, c.JCParentId, c.JCParentName
from JobCollection c
inner join cte p on p.JCId = c.JCParentId
)
select JCId, JCName, JCParentId, JCParentName
from cte as o
where not exists (
select 1
from cte as i
where o.JCid = i.JCParentId
);
测试设置:http://rextester.com/LGEQD6195
create table JobCollection (
JCId int
, JCName varchar(50)
, JCParentId int
, JCParentName varchar(50)
);
insert into JobCollection values
( 1, 'A' , null, null)
,( 2, 'B' , null, null)
,( 3, 'A1' , 1, null)
,( 4, 'A2' , 1, null)
,( 5, 'A3' , 1, null)
,( 6, 'B1' , 2, null)
,( 7, 'B2' , 2, null)
,( 8, 'A11', 3, null)
,( 9, 'A12', 3, null)
,(10, 'A21', 4, null)
,(11, 'A31', 5, null)
,(12, 'A32', 5, null)
,(13, 'B11', 6, null)
,(14, 'B12', 6, null)
,(15, 'B21', 7, null)
,(16, 'B22', 7, null);
查询:
declare @ParentId int;
set @ParentId = 1;
with cte as (
select JCId, JCName, JCParentId, JCParentName
from JobCollection
where JCId = @ParentId
union all
select c.JCId, c.JCName, c.JCParentId, JCParentName = p.JCName
from JobCollection c
inner join cte p on p.JCId = c.JCParentId
)
select JCId, JCName, JCParentId, JCParentName
from cte as o
where not exists (
select 1
from cte as i
where o.JCid = i.JCParentId
);
结果:
+------+--------+------------+--------------+
| JCId | JCName | JCParentId | JCParentName |
+------+--------+------------+--------------+
| 11 | A31 | 5 | A3 |
| 12 | A32 | 5 | A3 |
| 10 | A21 | 4 | A2 |
| 8 | A11 | 3 | A1 |
| 9 | A12 | 3 | A1 |
+------+--------+------------+--------------+
这应该有效!
SELECT distinct J1.*
from JobCollection J1
LEFT JOIN JobCollection J2 ON J1.JCId = J2.JcParentId
WHERE J2.JcParentId IS NULL