编写SQL查询以从表中获取唯一的超级子记录
我正在努力准备一个SQL查询,它应该一次返回预期的数据 我的要求是从名为JobCollection的SQl表中获取数据,该表将返回下图中以绿色边框突出显示的数据 该数据以父子方式组织。 正如你在下面看到的编写SQL查询以从表中获取唯一的超级子记录,sql,sql-server,select-query,Sql,Sql Server,Select Query,我正在努力准备一个SQL查询,它应该一次返回预期的数据 我的要求是从名为JobCollection的SQl表中获取数据,该表将返回下图中以绿色边框突出显示的数据 该数据以父子方式组织。 正如你在下面看到的 JCID1是JCID3,4,5的父ID。与JCID2相同的是JCID6,7的ParentID JCId 3、4、5也是8、9、10、11、12等的ParentId 条件: 我只想从JobCollection表中获取那些JCId不是任何其他记录父级的记录 如绿色边框中突出显示的,JCID
- JCID1是JCID3,4,5的父ID。与JCID2相同的是JCID6,7的ParentID李>
- JCId 3、4、5也是8、9、10、11、12等的ParentId
- 我只想从JobCollection表中获取那些JCId不是任何其他记录父级的记录李>
有很多方法。这是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)
更新:仅当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
Declare@YourTable表(JCId int、JCParentId int、JCName varchar(50))
在@YourTable值中插入
(1,NULL,'A')
,(2,空,'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')
声明@Top int=1--null--使用递归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, 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
逻辑上合理,但不在
中往往较慢。正确,但它给出了所需的结果。正如您所说……有很多方法可以做到这一点:-)@Svekke我在哪里添加一个JCId=1条件,因为我只需要超级父JCId为的记录1@Svekke通过准备我提供的数据,尝试自己运行更新后的查询,因为它在我的数据上为我提供空结果。该查询仅限于级别1。数据级别可以高达N个数字,除非您明确声明它是具有别名的同一个表,否则使用t1
和t2
在这里真的没有帮助。正如我提到的,我只想从JobCollection表中获取那些JCId不是任何其他记录的父级且其超级父级JCId为1的记录。这是一个极好的答案厕所。但我担心那些否决我的问题的人,因为这对我来说真的很难回答implement@CharanGhate你的问题在它的第一个版本中没有提出这个问题,现在完全不同了。
+------+--------+------------+--------------+
| 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