【问题标题】:Selecting from joined tables when relative rows might not exist当相关行可能不存在时从连接表中选择
【发布时间】:2018-07-07 13:33:49
【问题描述】:

TSQL 专家,我遇到了两个看起来像这样的表:

表格 - 名称

ID(pk)  Name
1       Peter
2       Paul
3       Mary
4       John
5       Fred

桌子 - 汽车

NameID(pk)  FieldNum    CarText
1           1           Ford
1           2           abcd123
1           3           Mustang
1           4           1967
1           6           Yellow
2           2           qwer456
2           4           1980
3           1           Chevrolet
3           3           Camaro
4           1           Chrysler
4           2           zxcv789
5           4           1970

由于第一个(名称)表中的所有名称都是必需的,但第二个表中只有 FieldNum = 2(如果存在)感兴趣,因此所需的输出将如下所示:

Name        CarText
---------------------
Peter       abcd123
Paul        qwer456
Mary        
John        zxcv789
Fred

或者就此而言,具有某种形式的空占位符的输出也可以使用:

Name        CarText
---------------------
Peter       abcd123
Paul        qwer456
Mary        foo
John        zxcv789
Fred        foo

各种文档建议将表连接更改为 LEFT(或 LEFT OUTER)连接是解决方案。没问题。

SELECT Name, CarText
 FROM Names
 LEFT JOIN Cars on Names.ID = Cars.NameID
WHERE Cars.FieldNum = 2

但这种方法正在交付:

Name        CarText
---------------------
Peter       abcd123
Paul        qwer456
John        zxcv789

因此,在业余地尝试了 RANK()、ROWNUM、CASE 和 WHERE EXISTS/NOT EXISTS 语句之后,感觉答案非常接近,但几天后我还是无法确定。

如何实现所需的输出,其中一个表是强制性的,但一个连接表仅在存在时提供相关字段(或如果需要,代替相关字段,某种无效值)?

【问题讨论】:

  • 过滤条件需要在JOIN而不是WHERE中。

标签: sql sql-server tsql sql-server-2016


【解决方案1】:

WHERE 子句将LEFT JOIN 转换为INNER JOIN。要保留不匹配的行,请将条件移至 ON 子句:

SELECT n.Name, c.CarText
FROM Names n LEFT JOIN
     Cars c
     ON n.ID = c.NameID AND c.FieldNum = 2;

【讨论】:

  • 谢谢戈登。现在我很高兴我问了 - 这种方法根本不在我的考虑范围内。
  • @KeyserSoze 另一种方法是在 where 子句中允许 NULL,例如... where Cars.FieldNum = 2 or Cars.FieldNum is NULL;... where Coalesce( Cars.FieldNum, 2 ) = 2;.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
  • 2017-08-29
  • 2012-11-10
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
相关资源
最近更新 更多