编写SQL查询以从表中获取唯一的超级子记录

时间:2017-02-03 12:45:11

标签: sql sql-server select-query

我正在努力准备一个应该一次性返回预期数据的SQL查询。

我的要求是从SQl表中获取名为 JobCollection 的数据,以便在下面的图像中以绿色边框突出显示数据。

此数据以Parent Child方式组织。 如下所示,

  • JCId 1是JCId 3,4,5的ParentID。与JCId 2相同的是JCId 6,7的ParentID。
  • JCId 3,4,5也是8,9,10,11,12的ParentId等等。

条件:

  • 我想只获取JobCollection表中那些JCId不是任何其他记录的父记录的记录。

如绿色边框所示,JCId 8,9,10,11和12不是任何记录的父母

此外,绿色边框突出显示JCId 1的超级孩子而不是JCId 2

请注意,这是一个示例,我们不能使用存储过程或游标。层次结构级别未定义。它可以是任何东西。

enter image description here

更新

又一个例子

我想只获得以红色突出显示的记录。如你所见,绿色边框告诉那些是每个记录的超级孩子,但红色突出了JCId 1的超级儿童记录

enter image description here

  

我衷心地向大家请求,请在仔细阅读问题之前仔细阅读并理解其中的痛苦。我很难获得预期的结果

5 个答案:

答案 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

<强>返回

enter image description here

@Top = NULL时的完整层次结构,您删除了最终版本,R1 = R2

enter image description here

答案 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