【问题标题】:SQL join to always return initial match and NULLs for subsequent mismatchesSQL 连接始终返回初始匹配,并为后续不匹配返回 NULL
【发布时间】:2015-06-08 04:38:44
【问题描述】:

如何创建一个连接,该连接始终为 Unit 中在 Test 中有一行的那些单元返回一行,即使 test 中的行在 TestDetail 中,其 PartID 中的行在 Part 中的 PartFamilyID 中具有PartFamily 中 Name 不等于 B 的行,在本例中为 B。换句话说,当后续连接为 false 时,始终为那些具有测试记录但具有 NULL 值的单元返回一条记录。

例如,从我预期的下面的代码中(我很抱歉我没有发布图片的声誉,我无法找到发布表格的方法):

u.ID t.IDt.UnitID td.ID td.TestID td.PartID p.ID p.PartFamilyID pf.ID pf.Name

1   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

2   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

2   15  2   114 15  1115    1115    11115   11115   E

3   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

4   14  4   113 14  1112    1112    11114   11114   D

4   16  4   115 16  1114    1114    11115   11115   E

5   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

declare @Results table (UnitID int, Value varchar(10))
insert into @Results (UnitID)
values (1),(2),(3),(4),(5)

declare @Unit table (ID int)
insert into @Unit
values (1),(2),(3),(4),(5),(6),(7)

declare @Test table (ID int, UnitID int)
insert into @Test
values (11,1),(12,1),(13,2),(14,4),(15,2),(16,4)

declare @TestDetail table (ID int, TestID int, PartID int)
insert into @TestDetail
values (111,11,1111),(112,13,1111),(113,14,1112),(114,15,1115),(115,16,1114)

declare @Part table (ID int, PartFamilyID int)
insert into @Part
values (1111,11112),(1112,11114),(1113,11114),(1114,11115),(1115,11115)

declare @PartFamily table (ID int, Name varchar(10))
insert into @PartFamily
values (11111,'A'),(11112,'B'),(11113,'C'),(11114,'D'),(11115,'E')

select *
from @Unit u
left join @Test t
on t.UnitID = u.ID
join @TestDetail td
on td.TestID = t.ID
join @Part p
on p.ID = td.PartID
join @PartFamily pf
on pf.ID = p.PartFamilyID
and pf.Name <> 'B'

但是,查询排​​除了 t.ID 为 NULL 的行,因此只剩下单元 2 和 4 的非 NULL t.ID 行。

我尝试了多种不同类型连接的组合,但均未成功。

最终,我想使用查询来更新表:

update r
set r.Value = case when t.ID is not NULL then 'Yes' else 'No' end
from @Results r
left join @Unit u
on u.ID = r.UnitID
left join @Test t
on t.UnitID = u.ID
join @TestDetail td
on td.TestID = t.ID
join @Part p
on p.ID = td.PartID
join @PartFamily pf
on pf.ID = p.PartFamilyID
and pf.Name <> 'B'

select * from @Results

当返回行时,这实际上有效。 如果返回 NULL t.ID 行,当单个单元的至少一行包含非 NULL t.ID 值时,我希望 case 语句的计算结果为 Yes。

我知道我可以随后更新值为 NULL 的 @Results,这很好。

但是,我仍在尝试了解如何获取要返回的所有单元的行。 我认为即使后续(内部)连接没有返回匹配项,左连接仍然会离开单元。

如果一个单元在Test中有匹配但测试记录在TestDetail中没有匹配,我怎样才能得到该单元的记录(后续表的列中的NULL值没有匹配)返回?

提前致谢!

【问题讨论】:

    标签: sql sql-server tsql join sql-update


    【解决方案1】:

    你必须在左连接之后进行左连接,因为你更新的方式会禁用t 的左连接,因为t.ID=null 永远找不到TestDetail td

    select r.*
         , r.ValueNew = case when t.ID is not NULL then 'Yes' else 'No' end
    from        @Results r
      left join @Unit u        on u.ID = r.UnitID
      left join @Test t        on t.UnitID = u.ID
      left join @TestDetail td on td.TestID = t.ID
      left join @Part p        on p.ID = td.PartID
      left join @PartFamily pf on pf.ID = p.PartFamilyID and pf.Name <> 'B'
    

    这样,你将拥有你的记录 r 而没有别的

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      相关资源
      最近更新 更多