我需要做这样的事情:
select *
from Table
inner join Few more tables
where t2.ID IN( case when @Param1 = 0 then
(select ID FROM tbl10 WHERE ForeignKey = @param2)
else @Param1 end)
因此,如果@Param1为0,那么我想要一些值匹配(基于@ param2),如果它不是0,我想只需@ Param1匹配。 我尝试了很少的语法变化,但它不会工作。
我也看到了类似的问题,但它对我没有帮助。
答案 0 :(得分:5)
使用OR
SELECT *
FROM table1 t1
INNER JOIN table2 t2
ON t1.t1col = t2.t1col
WHERE ( @param1 <> 0 AND t2.id = @Param1 )
OR ( @param1 = 0 AND t2.id IN (SELECT id
FROM tbl10
WHERE foreignkey = @param2) )
答案 1 :(得分:1)
select * from Table
inner join Few more tables
where t2.ID IN(select case when @Param1 = 0 then ID else @Param1 end FROM tbl10 WHERE ForeignKey = @param2)
答案 2 :(得分:1)
SELECT *
FROM Table
JOIN Few more tables
WHERE t2.ID IN (
SELECT @Param1 WHERE @Param1 <> 0
UNION ALL
SELECT ID FROM tbl10 WHERE ForeignKey = @param2 AND ISNULL(@Param1, 0) = 0
)
答案 3 :(得分:1)
我会完全不同地使用IF/ELSE
。通过将具有不同基数的两个不同标准混合在一起,您将降低优化者选择最佳查询计划的机会。使用以下内容可以获得更好的性能:
IF @Param = 0
BEGIN
SELECT *
FROM T
WHERE A IN (SELECT TID FROM T2 WHERE ID = 1 @param2);
END
ELSE
BEGIN
SELECT *
FROM T
WHERE ID = @Param1;
END
它看起来更像代码,因此应该效率低下但实际上并非如此。使用此测试场景:
CREATE TABLE T (ID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, A INT NOT NULL, B INT NULL);
INSERT T (A, B)
SELECT A, Number
FROM ( SELECT TOP 1000 A = RANK() OVER(ORDER BY a.object_id)
FROM sys.all_objects a
) a
CROSS JOIN (VALUES (1), (2), (3)) n (Number);
CREATE TABLE T2 (ID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, TID INT NOT NULL);
INSERT T2 (TID)
SELECT T.ID
FROM T
CROSS JOIN (VALUES (1), (2), (3)) n (Number);
CREATE NONCLUSTERED INDEX IX_T_A ON T (A);
CREATE NONCLUSTERED INDEX IX_T2_TID ON T2 (TID);
GO
CREATE PROCEDURE dbo.Proc1 @Param1 INT, @Param2 INT
AS
SELECT ID, A, B
FROM T
WHERE ( @param1 <> 0 AND t.A = @Param1 )
OR ( @param1 = 0 AND t.A IN(SELECT TID FROM T2 WHERE ID = @param2));
-- (SORRY TIM, BUT YOURS WAS THE BEST OF THE REST)
GO
CREATE PROCEDURE dbo.Proc2 @Param1 INT, @Param2 INT
AS
IF @Param1 = 0
BEGIN
SELECT ID, A, B
FROM T
WHERE A IN (SELECT TID FROM T2 WHERE ID = @param2);
END
ELSE
BEGIN
SELECT ID, A, B
FROM T
WHERE A = @Param1;
END
GO
如果运行第一个过程(没有IF),由于SQL-Server不知道@ Param1和@Param2将在编译时是什么,它不知道将满足哪个条件,因此无法优化因此,为两个条件创建相同的计划
EXECUTE dbo.Proc1 1, 1;
EXECUTE dbo.Proc1 0, 1;
然而,如果您使用IF/ELSE
SQL-Server可以为每个条件创建最佳计划:
EXECUTE dbo.Proc2 1, 1;
EXECUTE dbo.Proc2 0, 1;
在这种情况下,实际影响并不像查询计划所建议的那样糟糕,因为SQL-Server在运行时足够聪明,不评估子项如果@Param1 = 0
从T2中选择,我不是说从来没有使用多个OR
条件的情况,但通常当你有一个影响你想要的谓词的常量时,最好将它与IF / ELSE分开,而不是将两个谓词混合在一起。
有时,较少的代码并不总是更有效的查询。
答案 4 :(得分:0)
简单有效:
select * from Table
inner join Few more tables
where
-- IF
@Param1 = 0
and t2.id in (select ID FROM tbl10 WHERE ForeignKey = @param2)
-- ELSE
or t2.id = @Param1
答案 5 :(得分:0)
我喜欢和接近IF语句,但是如果你不喜欢它,请尝试使用UNION ALL
SELECT *
FROM table1 t1
INNER JOIN table2 t2
ON t1.t1col = t2.t1col
WHERE @param1 <> 0 AND t2.id = @Param1
UNION ALL
SELECT *
FROM table1 t1
INNER JOIN table2 t2
ON t1.t1col = t2.t1col
INNER JOIN tbl10
ON t2.ID =tbl10.ID
AND foreignkey = @param2
WHERE @param1 = 0