Conditional statement in WHERE clause - sql

I need to write a conditional statement in my where clause that uses different operators based on the parameter passed into the procedure. I can't seem to find the syntax that will work.
My example is as follows:
#DateValue datetime
select *
from table
where field1 = 'x'
and field2 = 'y'
and if #DateValue = '1/1/1900' then
field3 <= getdate()
else
field3 = #DateValue
end
Thanks for everyone's assistance.

and ((#DateValue = '1/1/1900' and field3 <= getdate()) or
(#DateValue <> '1/1/1900' and field3=#DateValue))

I think you would need something like (psuedo-code)
Create PROCEDURE GetPartialTable
#DateValue datetime
AS
Begin
IF (#DateValue = '1900-01-01')
select * from table where field1 = 'x' and field2 = 'y' and field3 <= getdate();
else
select * from table where field1 = 'x' and field2 = 'y' and field3 = #DateValue;
END IF
END
It sounds like the solution above, but the results might be seriously different if the context is more general, e.g. if the entire SQL statement is completely different.

Related

SQL: CASE expression with declared variable

I have following example that doesn't work in SQL server.
table1.field1 is also a char(3)
DECLARE #CALCULATED_FIELD char(3);
SELECT table1.field1
,table1.field2
,CASE
WHEN table1.field2 = '1' THEN #CALCULATED_FIELD = table1.field1
ELSE #CALCULATED_FIELD = 'ALL'
END
FROM table1
Anyone knows the problem with the case statement?
A SQL Server SELECT statement can either assign variable values or return rows, but not both. You might intend:
SELECT #CALCULATED_FIELD = COALESCE(table1.field1, 'ALL')
FROM table1;
This would assign the maximum value to the variable -- and the only value if the table has only one row. If the table has no rows, the variable would be assigned 'ALL'.
The result of the CASE expression must be assigned to the variable, but it is not allowed in the same statement to return any columns from the table.
So this:
SELECT
#CALCULATED_FIELD = CASE
WHEN field2 = '1' THEN field1
ELSE 'ALL'
END
FROM table1
is syntactically valid, although it will assign to the variable finally, the result of the CASE expression of the last row fetched.
By the name of the variable, I suspect that you want a 3d column which will be calculated by CASE:
SELECT field1, field2,
CASE
WHEN field2 = '1' THEN field1
ELSE 'ALL'
END calculated_field
FROM table1
See a simplified demo.
I would use a scaler funtion in this case
CREATE FUNCTION calcfield
(
#field2 VARCHAR(4),
#field1 VARCHAR(4)
)
RETURNS VARCHAR(3)
AS
BEGIN
DECLARE #CalcField CHAR(3)
SELECT #CalcField = CASE
WHEN #field2 = '1' THEN #field1
ELSE 'ALL'
END
RETURN #CalcField
END
GO
and then change your query to
SELECT table1.field1
,table1.field2
,dbo.calcfield(table1.field2,table1.field1)
FROM table1
Expressions like A=B is not a scalar value. So when you run the following query, it fails and you will get an error Incorrect syntax near '='.
SELECT ('aaa' = 'aaa')
In your case
CASE WHEN table1.field2 = '1'
THEN #CALCULATED_FIELD = table1.field1
ELSE #CALCULATED_FIELD = 'ALL'
END
is not a valid expression, and you might mean something like
CASE WHEN table1.field2 = '1'
THEN (CASE WHEN #CALCULATED_FIELD = table1.field1 THEN 1 ELSE 0)
ELSE (CASE WHEN #CALCULATED_FIELD = 'ALL' THEN 1 ELSE 0)
END
Please note that you can run a query like
SELECT columnName = 'aaa'
and it works as
SELECT 'aaa' AS columnName
Thx a lot.
For the create function, I have no rights and we can't do it on the production environment. But would work. Nice.
The example from forpas used and it works perfect for me.

Selecting a specific value within a case statement

I need help with selecting a specific value within a CASE Statement.
For an example
SELECT CASE WHEN Field1 >= (Field2 = 1) THEN Answer
WHEN Field1 < (Field2 = 1) THEN No Answer
ELSE Question END AS Field3
I want to be able to select a specific value in Field2 within the CASE Statement
could be you are looking for
SELECT CASE WHEN Field1 >= Field2 AND Field2 = 1 THEN Answer
WHEN Field1 < Field2 AND Field2 = 1 THEN No Answer
ELSE Question END AS Field3
or more simply
SELECT CASE WHEN Field1 >= 1 THEN Answer
WHEN Field1 < 1 THEN No Answer
ELSE Question END AS Field3
-- 1. You don't specify the fields types.
-- 2. You do a comparison of Field1 with a logical expression (Field2=1). i guess it fails.
-- 3. I will assume Answer, No answer and Question will be the desired string result, and have to be quoted.
-- 4. A Table name is missing. I will assume Field1 and Field2 are fields from MyTable
-- 5. I' am assuming Field1 and Field2 of the same type, and be varchar(10) for example.
DECLARE #Field2 varchar(10) = 1
SELECT
CASE WHEN Field1 >= Field2 THEN 'Answer'
WHEN Field1 < Field2 THEN 'No Answer'
ELSE 'Question'
END AS Field3
FROM MyTable
WHERE Field2 = #Field2

Use variable sql for column name

Before you shout at me in CAPS for not searching - I have! Dynamic SQL is good, dynamic SQL is bad. Learning a lot..
I can accomplish what I'm after by using logic in there WHERE clause, but it adds a significant amount of run time. The query takes 8 seconds if I hard code the criteria and 1:20 if I use the WHERE logic.
Here is what I'd like to do:
Declare #EmployeeToggle varchar(30)
Declare #Employee_ID varchar(30)
Declare #EmployeeField varchar(100)
set #EmployeeToggle = '1'
set #Employee_ID = '1166'
set #EmployeeField = case when #EmployeeToggle = '1' then 'Field1' else
'Field2' end;
select * from Table1 where #EmployeeField = #Employee_ID
I don't think it's possible without dynamic sql. I still don't know whether or not I should use it. It's my thought that it would take the query back down to 8 seconds, because it would immediately know which field to use in the where clause.
Alternatively, a few ways to do it in the where only:
where (( not #EmployeeToggle = '1') or Field1 = #Employee_ID) and
(#EmployeeToggle = '1' or Field2 = #Employee_ID)
where (1=(case when #EmployeeToggle = '1' then 1 else 0 end ) or Field1 =
#Employee_ID)
and (1=(case when #EmployeeToggle = '2' then 1 else 0 end) or Field2 =
#Employee_ID)
These work great (admittedly I copied and pasted these examples), but at the expense of run time.
My final thought, and the way others have done it at my org, is to create two scripts that are identical except for the field used in the where clause. So, if #EmployeeToggle = '1' it will run the first script and if it's '2' it will run the second. I haven't tried that yet, but I assume the runtime will be closer to the 8 seconds at the expense of some ugly code.
Thanks for the help.
Why not just use a single query?
select t.*
from table1
where #EmployeeToggle = '1' and field_1 = #Employee_ID
union all
select t.*
from table1
where #EmployeeToggle <> '1' and field_2 = #Employee_ID;
By using union all, SQL Server should use indexes for each subquery -- and if you have indexes on the fields, the query should be fast.
You can stay with static SQL when using CASE expression in SELECT then filter it.
SELECT *
FROM (
SELECT *,
CASE WHEN #EmployeeToggle = '1' THEN Field1 ELSE Field2 END AS Field1_2
FROM Table1
) t
WHERE
Field1_2 = #Employee_ID
Here is your dynamic query:
Declare #EmployeeToggle varchar(30)
Declare #Employee_ID varchar(30)
Declare #EmployeeField varchar(100)
set #EmployeeToggle = '1'
set #Employee_ID = '1166'
set #EmployeeField = case when #EmployeeToggle = '1' then 'Field1' else
'Field2' end;
DECLARE #SQLString VARCHAR(MAX)
SET #SQLString='select *
from Table1
where '+#EmployeeField+' = '+#Employee_ID+''
PRINT(#SQLString) --If you want to check actual query
EXEC(#SQLString)

TSQL where case

I need the correct tsql syntax for this problem :
Select * from table where var_A='10'
select * from table where var_B='10'
When to use var_A or var_B depends on the value of var_C
So when var_c='something' use var_A='10' else var_B='10'
select *
from [table]
where case when var_c = 'something' then var_a else var_b end = '10'
SQL Fiddle with demo.
Ian probably has the best answer available but I thought I would supply another answer for a different (although less flexible) method in case it helps:
IF var_c = 'something' BEGIN
SELECT * FROM [table] WHERE var_a = '10'
END
ELSE BEGIN
SELECT * FROM [table] WHERE var_b = '10'
END
This how you use case statement within where clause.
select * from table
where ( case when var_c = 'something'
then var_a
else
var_b
end
)

Sql where clause

I have a stored procedure where I am passing a value to be used in the select statement in the where clause.
If the value that I am passing is NULL, I do not want it to be part of that portion of the where clause where it is used. In the example below, variable2 is the variable I am passing to the stored procedure and using in the sql statement but if #variable2 is NULL, I do not want to use variable2= #val1 in the where clause. Example:
select Field1, Field2 from tbl1
where variable2= #val1
and ID = 'test'
Try:
where (#val1 is null or variable2 = #val1)
and ID = 'test'
select Field1, Field2 from tbl1
where (variable2= #val1 or #val1 is null)
and ID = 'test'
How about:
select Field1, Field2 from tbl1
where (#val1 IS NULL or variable2 = #val1)
and ID = 'test'
Your WHERE clause should have the column on the left side, and that could possibly be the case but you are calling it variable2. This would work, given specific parameters:
select Field1, Field2
from tbl1
where yourColumn =
case
when #param1 is null
then #param2
end
I have used a generic field name and parameter names, but you should get the idea.