编写 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 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