Case statement to switch the column being compared in sql where clause - sql

I have a scenario where the column that I need to use in the where clause changes based on the value of a variable.
For example if #ID matches the TableID in Table1 then I'll use the code below
WHERE
Table1.TableID = CASE WHEN #ID= -1 THEN Table1.TableID ELSE #ID END
However, if the #ID matches the TableID of Table2 Then I need to use
WHERE
Table2.TableID = CASE WHEN #ID= -1 THEN Table2.TableID ELSE #ID END
How will I accomplish this? Will the OR clause work in this scenario?
Edit: Trying to provide more detail to make it more clear.
Sample data
Table 1
TableID
1
2
3
4
Table 2
TableID
10
11
12
13
If the #ID = -1 I want to see all the rows from both the tables.
If #ID = 1 then only show the first row from Table 1
If #ID = 10 then only show the last row from Table 2...and so on.

Couldn't you just do something like this.
where (#ID = Table1.TableID OR #ID = Table2.TableID)
If you are looking to see if #ID matches either of these tableID's than this seems like a much simpler way of doing it.

Try something like this....
WHERE
(#ID = -1 AND Table1.TableID = #ID)
OR
(#ID = -1 AND Table2.TableID = #ID)
It doesnt make sense the way you have asked the question, you have same value in both cases for #ID it could have been a simpler query something like this...
WHERE
(Table1.TableID = #ID)
OR
(Table2.TableID = #ID)

WHERE #ID IN (
Table1.TableID
,Table2.TableID
,-1
)

Try this minimal sum of products clause. Given the information available, this is the most I can tell you to do without blindly guessing at the structure of your query and DB:
WHERE
(Table1.TableID = #ID AND #ID <> -1) OR (Table2.TableID = #ID AND #ID <> -1)

Related

Use NULL as a valid value in a stored procedure

I have a stored procedure with one parameter, #ID, which is an integer that might be zero. When it is zero, I want to use it as if it is null. So here is how I have written my query:
If #ID = 0
SELECT * FROM MyTable WHERE ID IS NULL
ELSE
SELECT * FROM MyTable WHERE ID = #ID;
This is quite inelegant. Surely there is a way to write the WHERE clause in such a way that makes duplicating the SELECT statement unnecessary.
You can phrase this more simply using:
SELECT *
FROM MyTable
WHERE COALESCE(ID, 0) = #id;
Next, you probably do not want to do this. It will prevent SQL Server from using an index. Similarly, OR is likely to prevent optimization as well.
Probably your best bet is your current code, or UNION ALL:
SELECT *
FROM MyTable
WHERE ID IS NULL AND #id = 0
UNION ALL
SELECT *
FROM MyTable
WHERE ID = #ID; -- not sure if `#id <> 0` is needed here
With this or your approach, you probably need OPTION (RECOMPILE) to ensure that an index is always used.
Just combine them using AND/OR logic:
SELECT *
FROM MyTable
WHERE (#Id != 0 AND ID = #ID)
OR (#Id = 0 AND ID IS NULL);

Case statement in WHERE clause in SQL [duplicate]

This question already has answers here:
SQL Switch/Case in 'where' clause
(14 answers)
Closed 8 years ago.
I have a table 'Route' with Id ,Name and Active columns. If Id = 0 I want to select all the Id's where Active = true.
If Id > 0 I want to select the data for particular Id where Active = true.
I tried with following Query. But not working. (here I passed 2 for a Id value.)
Can someone support me?
DECLARE #ID INT
SET #ID = 2
SELECT DISTINCT Id ,Name
FROM Route
WHERE
CASE WHEN #ID > 0
THEN Id = #ID AND Active= 1
ELSE
Active=1
END
Sample Data Attached.
No need to use case can be done using where clause only.
DECLARE #ID INT
SET #ID = 2
SELECT DISTINCT Id ,Name
FROM Route
WHERE Active=1 AND (Id = #Id OR #Id = 0);
Explanation:
WHERE
CASE WHEN #ID > 0
THEN Id = #ID AND Active= 1
ELSE
Active=1
a. if #ID > 0 then Id = #ID AND Active= 1
b. else Active=1
If you look into both cases closely, Active= 1 remains same in both cases so it can be taken safely to outside of the condition
Then the remaining part is, if #ID > 0 then Id = #ID i.e. select the row as per the parameter value when parameter has valid value, otherwise select all.
So, if you combine both it becomes
WHERE Active=1 AND (Id = #Id OR #Id = 0);

Conditional filter in WHERE clause

How can I set a conditional filter in a SQL WHERE clause? For example, I have a parameter #ID with the following procedure
SELECT * FROM myTable WHERE Column1 = 'test' AND Column2 = #ID
However, If #ID = -1 I don't want the last part of the SQL (AND Column2 = #ID) included
I realize I can make an if statement with 2 separate queries, however this is a large script and has this same issue multiple times, so I was hoping there was a better way than nearly duplicating several queries
This is ok for T-SQL:
SELECT * FROM myTable WHERE Column1 = 'test' AND (#ID = -1 OR Column2 = #ID)
Just include the condition in your SQL as an OR, note the brackets
SELECT * FROM myTable WHERE Column1 = 'test' AND (#ID = -1 OR Column2 = #ID)
One alternative:
SELECT * FROM myTable WHERE Column1 = 'test' AND #ID in (-1,Column2)

Querying different table based on a parameter

I have a stored procedure that I would like to query either the production or the "work in progress" table, based on the parameter I am passing in. I could write two separate stored procedures, but I thought this was worth a try.
something along the lines of:
create procedure getUserDetails
#userID int,
#prod varchar(5)
as
begin
select * from
if (#prod = 'true')
Begin
userprod_table
else
userwip_table
end
where something = 'something'
END
Is this at all possible? I wouldn't want to write 2 SP that are almost identical :-/
Why not use a simple if(#prod = 'true') statement like below:
if (#prod = 'true')
begin
select * from userprod_table where something = 'something'
end else
begin
select * from userwip_table where something = 'something'
end
You could use a CTE so that your main query isn't repeated
with usertable as
(
select * from userprod_table where 1 = #flag
union
select * from userwip_table where 0 = #flag
)
select ... from usertable ...

Quicker way to update all rows in a SQL Server table

Is there a more efficient way to write this code? Or with less code?
SELECT *
INTO #Temp
FROM testtemplate
Declare #id INT
Declare #name VARCHAR(127)
WHILE (SELECT Count(*) FROM #Temp) > 0
BEGIN
SELECT TOP 1 #id = testtemplateid FROM #Temp
SELECT TOP 1 #name = name FROM #Temp
UPDATE testtemplate
SET testtemplate.vendortestcode = (SELECT test_code FROM test_code_lookup WHERE test_name = #name)
WHERE testtemplateid = #id
--finish processing
DELETE #Temp Where testtemplateid = #id
END
DROP TABLE #Temp
You can do this in a single UPDATE with no need to loop.
UPDATE tt
SET vendortestcode = tcl.test_code
FROM testtemplate tt
INNER JOIN test_code_lookup tcl
ON tt.name = tcl.test_name
You could try a single update like this:
UPDATE A
SET A.vendortestcode = B.test_code
FROM testtemplate A
INNER JOIN test_code_lookup B
ON A.name = B.test_name
Also, the way you are doing it now is wrong, since you are taking a TOP 1 Id and a TOP 1 name in two separate querys, without an ORDER BY, so its not sure that you are taking the right name for your ID.
You could write a function to update vendortestcode. Then your code reduces to one SQL statement:
update testtemplate set vendortestcode = dbo.get_test_code_from_name(name)