我正在尝试像这样实现条件连接
declare @JoinWithT2 bit = 1;
select T1.* from T1
inner join T2 on (@JoinWithT2 = 0 or T1.Id=T2.Id)
这很好,当我传递@JoinWithT2
值1时,它使用两个表的连接给我结果,当我传递@JoinWithT2
值0时,它返回T1的所有结果,忽略连接
这一切都运作良好,但我担心性能,因为上述也可以像这样实现
if @JoinWithT2=0
begin
select T1.* from T1
end
else
begin
select T1.* from T1
inner join T2 on (T1.Id=T2.Id)
end
实现条件连接的最佳方法是什么,第一个或第二个?
我个人认为第二个应该更好的表现,因为它根本不涉及T2而第一个查询可能正在使用T2
答案 0 :(得分:2)
我很困惑。以下应该是笛卡尔积或内连接,具体取决于JoinWithT2
:
declare @JoinWithT2 bit = 1;
select T1.*
from T1 inner join
T2
on (@JoinWithT2 = 0 or T1.Id=T2.Id);
当@JoinWithT2
为0
时,on
子句始终为true。这使得join
相当于cross join
。
以下是进行连接或获取第一个表的条件逻辑:
declare @JoinWithT2 bit = 1;
select T1.*
from T1 left outer join
T2
on (@JoinWithT2 = 1 and T1.Id=T2.Id)
where @JoinWithT2 = 0 or T2.Id is not null;
从性能角度来看,if
中的单独语句通常会表现得更好。 SQL引擎有更多信息可供优化。但是,如果您在T2(id)
上有索引,那么相对于查询的其他部分,性能差异可能不会很大,例如将结果返回给用户。
答案 1 :(得分:1)
在这种情况下,最好的选择可能是动态SQL,或者在较新版本的SQL服务器中条件不如旧版本那么糟糕。 if语句很好但在添加两个或三个其他表之后很难维护,这些表可能会或可能不会根据特定条件加入。随着时间的推移,或者条件可能会变慢,并且会向查询添加更多内容。仅使用此特定参数集所需的内容构建搜索类型查询通常是最佳选择。
您可能需要阅读:
http://www.sommarskog.se/dyn-search-2008.html
或(如果您使用SQL SERVER 2005或更早版本) http://www.sommarskog.se/dyn-search-2005.html
答案 2 :(得分:1)
如果您不从T2中选择任何内容,为什么还需要加入?同样可以通过以下方式实现:
select T1.*
from T1
where @JoinWithT2 = 0 or T1.Id in (select T2.Id from T2);
答案 3 :(得分:1)
静态解决方案:
CREATE VIEW Person.vBusinessEntityAddressWithInfo
AS
SELECT bea.AddressID,bea.AddressTypeID,bea.BusinessEntityID,bea.ModifiedDate,
a.PostalCode AS AddressPostalCode,a.City AS AddressPostalCity
FROM Person.BusinessEntityAddress bea
JOIN Person.[Address] a ON bea.AddressID=a.AddressID;
GO
-- Test #1: columns from only one table Person.BusinessEntityAddress
SELECT v.AddressID,v.BusinessEntityID
FROM Person.vBusinessEntityAddressWithInfo v
GO
-- Test #2: columns from both tables
SELECT v.AddressID,v.BusinessEntityID,v.AddressPostalCode
FROM Person.vBusinessEntityAddressWithInfo v
GO
如果我查看执行计划,那么我可以看到Test #1
SQL Server仅使用Person.BusinessEntityAddress
表(请参阅FK elimination
;另请参阅此answer)以及Test #2
SQL Server使用两个表:
另一个“静态”(或多或少)解决方案:
DECLARE @Type BIT;
SET @Type=0;
SELECT bea.*,NULL AS AddressPostalCode,NULL AS AddressPostalCity
FROM Person.BusinessEntityAddress bea
WHERE @Type=0
UNION ALL
SELECT bea.*,a.PostalCode AS AddressPostalCode,a.City AS AddressPostalCity
FROM Person.BusinessEntityAddress bea
JOIN Person.[Address] a ON bea.AddressID=a.AddressID
WHERE @Type=1;
如果我使用@Type=0
和SET STATISTICS IO ON
执行此查询,则SQL Server将从BusinessEntityAddress
读取数据:
Table 'Worktable'. Scan count 0, logical reads 0
Table 'Worktable'. Scan count 0, logical reads 0
Table 'BusinessEntityAddress'. Scan count 1, logical reads 112
当我用@Type=1
执行相同的查询时,SQL Server将从两个表中读取数据:
Table 'Worktable'. Scan count 0, logical reads 0
Table 'Address'. Scan count 1, logical reads 216
Table 'BusinessEntityAddress'. Scan count 1, logical reads 112
Table 'Worktable'. Scan count 0, logical reads 0