SQL Server - 选择左连接 NULL 记录 WHERE 条件

Posted

技术标签:

【中文标题】SQL Server - 选择左连接 NULL 记录 WHERE 条件【英文标题】:SQL Server - Select Left Join NULL record WHERE condition 【发布时间】:2011-08-16 09:11:20 【问题描述】:

我正在尝试对使用 LEFT JOIN 连接的两个表执行 SELECT 查询,其中连接的表中可能没有记录。比如:

--SELECT row using AreaID
SELECT *
FROM Rate
LEFT JOIN Area
ON Rate.AreaID = Area.AreaID
WHERE ProductID = @ProductID
AND Area.PostcodeOutcode = @PostcodeOutcode

这在Area表中存在@PostcodeOutcode时有效,但是如果右表中没有记录,我仍然需要返回左表中的记录。

我目前正在这样做,但我知道有更好的解决方案:

DECLARE @AreaID int
SELECT @AreaID = AreaID
FROM Area WHERE PostcodeOutcode = @PostcodeOutcode 

--SELECT row using AreaID
SELECT *
FROM Rate
WHERE ProductID = @ProductID
AND
(
    AreaID = @AreaID
    OR (@AreaID IS NULL AND AreaID IS NULL)
)

我知道这可能很简单,但我的 SQL 知识有限。请帮忙。

谢谢

亚历克斯

【问题讨论】:

您明白 SELECT * 是 SQL 反模式吗?您返回的超出了您的需要(至少重复连接字段),这对性能不利。生产代码一般不应包含 select *。 【参考方案1】:

将区域检查移动到连接处

SELECT * FROM Rate
LEFT JOIN Area 
  ON Rate.AreaID = Area.AreaID and Area.PostcodeOutcode = @PostcodeOutcode
WHERE ProductID = @ProductID 

更新 cmets 中修改后的问题,这是你想要的吗?

SELECT Rate.RatePercent FROM Rate
INNER JOIN Area 
  ON Rate.AreaID = Area.AreaID and Area.PostcodeOutcode = @PostcodeOutcode
WHERE 
  ProductID = @ProductID
UNION ALL
SELECT Rate.RatePercent FROM Rate 
where
  ProductID = @ProductID 
and 
  AreaId is null 
and 
 not exists(select PostCodeOutCode From Area where PostCodeOutCode=@PostCodeOutcode)

【讨论】:

也许我问错了问题。我只想返回一行。请参阅上面我捏造的解决方案。即如果 Area.PostcodeOutcode 不是 null,则从连接返回 Rate.RatePercent。如果 Area.PostcodeOutcode null,则返回 Rate.RatePercent 其中 Rate.AreaID 为 null。谢谢亚历克斯 就是这样!谢谢你。我期待着一些更简单的东西。这比我目前的做法更有效率吗? 仅因为它使用单个查询而不是两次提取,最好的办法是在查询计划器中检查两者并查看成本是多少【参考方案2】:

这两者的左连接是有区别的:

Select *
From Table1 t1
Left Outer Join Table2 t2 On t2.id = t1.id
Where t2.somevalue = @SomeParameter

Select *
From dbo.Table1 t1
Left Outer Join dbo.Table2 t2 On t2.id = t1.id And t2.somevalue = @SomeParameter

后者将过滤Table2,而前者将过滤Table1和Table2之间的连接。因此,这意味着第一个查询将在 id 上连接两个表中的所有行,然后过滤 somevalue 与参数不匹配的行,即这通常也会过滤掉 somevalue 为空的行,因为没有行。

第二个查询会在id上将table1和table2连接起来,但是table2首先会根据匹配的参数进行过滤,所以不匹配的行也会被返回,因此不会被过滤掉。

附带说明:您应该始终在查询中提供表的架构(出于性能原因)。

【讨论】:

以上是关于SQL Server - 选择左连接 NULL 记录 WHERE 条件的主要内容,如果未能解决你的问题,请参考以下文章

sql左连接查询多出记录的问题

将 SQL 转换为带有 null 的 Linq 左连接

SQL Server 2008 R2——内连接 左连接 右连接 全连接 交叉连接

如果不是 Null,则检查输入参数并在 SQL Server 的 where 中使用它

SQL Server 使用“或”运算符左连接

SQL Server内连接左外连接右外连接完全连接交叉lianjie