2011-08-16 43 views
3

我想执行一个SELECT查询连接到一个LEFT JOIN连接表中可能没有记录的两个表上。喜欢的东西:SQL Server - 选择左连接NULL记录在哪里条件

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

这工作时,在区表中存在@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知识是有限的。请帮忙。

感谢

亚历

+1

你确实在说SELECT *是一个SQL反模式?你的回报超过了你的需要(在最少的情况下连接字段重复),这对性能不利。生产代码通常不应包含select *。 – HLGEM

回答

5

移动区域检查联接

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

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

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 [email protected]) 
+0

也许我问了错误的问题。我只想返回一行。看到我上面的模糊解决方案。 即,如果_Area.PostcodeOutcode_ **不是** null,则返回来自连接的_Rate.RatePercent_。如果_Area.PostcodeOutcode_ **为null,则返回_Rate.RatePercent_,其中_Rate.AreaID_为null。 谢谢 亚历克斯 – Alex

+0

就是这样!谢谢。我期待或许更简单一些。这比我目前的做法更有效率吗? – Alex

+0

只是因为它使用的是单个查询而不是两次提取,所以最好的方法是在查询计划器中查看两个查询,看看成本是多少 –

4

有左差别加入这两者之间:

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 

后者将过滤表2,而前者将过滤表1和表2之间的连接。所以,这意味着第一个查询将连接id上的两个表中的所有行,然后过滤某个值与参数不匹配的那些行,即通常也会过滤出somevalue为null的那些行,因为没有行。

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

另外还有一个提示:应该始终在查询中提供表的模式(出于性能原因)。