我正在努力准备一个应该一次性返回预期数据的SQL查询。
我的要求是从SQl表中获取名为 JobCollection 的数据,以便在下面的图像中以绿色边框突出显示数据。
此数据以Parent Child方式组织。 如下所示,
条件:
如绿色边框所示,JCId 8,9,10,11和12不是任何记录的父母
此外,绿色边框突出显示JCId 1的超级孩子而不是JCId 2
请注意,这是一个示例,我们不能使用存储过程或游标。层次结构级别未定义。它可以是任何东西。
更新
又一个例子
我想只获得以红色突出显示的记录。如你所见,绿色边框告诉那些是每个记录的超级孩子,但红色突出了JCId 1的超级儿童记录
我衷心地向大家请求,请在仔细阅读问题之前仔细阅读并理解其中的痛苦。我很难获得预期的结果
答案 0 :(得分:1)
有很多方法。这是1。
select whatever
from table t1 left join table t2 on jcid = jcparentid
where t2.jcid is null
答案 1 :(得分: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
<强>返回强>
@Top = NULL时的完整层次结构,您删除了最终版本,R1 = R2
答案 2 :(得分:1)
使用递归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 |
+------+--------+------------+--------------+
答案 3 :(得分:0)
我会试一试:
SELECT JcId FROM JobCollection
WHERE JcId NOT IN (SELECT JcParentId FROM JobCollection)
更新:仅在JcParentId = 1
时选择SELECT JcId FROM JobCollection
WHERE JcId NOT IN (SELECT JcParentId FROM JobCollection)
AND JcParentId = 1
答案 4 :(得分:0)
这应该有效!
SELECT distinct J1.*
from JobCollection J1
LEFT JOIN JobCollection J2 ON J1.JCId = J2.JcParentId
WHERE J2.JcParentId IS NULL