Reputation: 161
I need to do something like this:
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)
So if @Param1 is 0 then i want some set of values to be a match(based on the @param2),and if its not 0 i want just @Param1 to match. i have tried few syntax variations but it wont work.
I have also seen a similar question,but it didn't help me.
Upvotes: 0
Views: 2204
Reputation: 311
I like and approach with IF statement, but if you don't like it, try this, with 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
Upvotes: 0
Reputation: 69759
I would approach this completely differently and use IF/ELSE
. By mashing together two different criteria with different cardinality you are lowering the optimisers chances of choosing the best query plan. You will get much better performance using something like this:
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
It looks like more code, so should be less efficient but it really isn't. Using this test scenario:
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 run the first procedure (with no IF), since SQL-Server doesn't know what @Param1 and @Param2 will be at compile time, it doesn't know which condition will be met, so can't optimise accordingly, so creates the same plan for both conditions
EXECUTE dbo.Proc1 1, 1;
EXECUTE dbo.Proc1 0, 1;
Whereas, if you use IF/ELSE
SQL-Server can create the optimal plan for each condition:
EXECUTE dbo.Proc2 1, 1;
EXECUTE dbo.Proc2 0, 1;
In this instance the actual impact is not as bad as the query plans suggest, since SQL-Server is smart enough at run time not to evaluating the subuqery to select from T2 if @Param1 = 0
, and I am not saying there is never a case for using multiple OR
conditions, but usually when you have a constant that affects the predicate you want it is best to separate it with an IF/ELSE rather than mashing together two predicates.
Sometimes less code is not always a more efficient query.
Upvotes: 1
Reputation: 1396
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
)
Upvotes: 1
Reputation: 39393
Simple and effective:
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
Upvotes: 0
Reputation: 460068
Use 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) )
Upvotes: 5
Reputation: 2629
can you try this
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)
Upvotes: 1