"IN" condition at CASE WHEN on WHERE CLAUSE? - sql

I have an complex situation. I want to write an sql query including "case when" condition on "where clause".
Just like that:
SELECT *
FROM <table>
WHERE
<Column1> in
CASE <Column2>
WHEN 1 THEN ('OP', 'CL')
WHEN 0 THEN ('RE', 'ST')
END
Column1 must be "in", not "=". Because there is multiple value at condition for Column1. That query returns "Incorrect syntax near ','." error.
Can you give me any suggestion? (Sorry for my bad English.)
EDIT : I think I misunderstood. If Column2 is 1, condition must like that "IN ('OP', 'CL')" else Column1 is 2, condition must like that "IN ('RE', 'ST')".

You don't need a CASE expression for that, you can just use OR like this:
SELECT *
FROM <table>
WHERE (Column2 = 1 AND Column1 IN ('OP', 'CL')) OR
(Column2 = 0 AND Column1 IN ('RE', 'ST'))

Select * from table where <Column1> in (Select case <Column2> when 1 then ('OP','CL') when
0 then ('RE','ST'))

Related

How do I update multiple tables with multiple where clauses in one query

Is there a way to do multiple updates with one sql query?
Something like:
UPDATE Table1
SET Column1 = Expression1 WHERE Conditions 1
SET Column2 = Expression2 WHERE Conditions 2
SET Column3 = Expression3 WHERE Conditions 3
...;
Thank you!
Yes, it looks like an anti pattern, but, syntactically, you can do it using Case expression:
UPDATE Table1
SET
Column1 = ( case when condition1 then Expression1 else Column1 end ),
Column2 = ( case when condition2 then Expression2 else Column2 end )
By the way, I guess you mixed "multiple tables" by "multiple columns".

Case when statement in SQL

I am using the following query. In this query I want to apply the where clause based on passed parameter. But the issue is that where clause is like 'value = if parameterVal = 'I' than NULL else NOT NULL'
I've build a query like this
SELECT * FROM MASTER
WHERE
Column1 IS (CASE WHEN :Filter = 'I' THEN 'NULL' ELSE 'NOT NULL' END)
but it's not working. Help me solve this.
UPDATE
Updating question to elaborate question more clearly.
I've one table MASTER. Now I am passing one parameter in query that is Filter (indicated by :Filter in query).
Now when the Filter parameter's value is 'I' than it should return the following result.
SELECT * FROM MASTER WHERE Column1 IS NULL
but if the passed argument is not equal to 'I' than,
SELECT * FROM MASTER WHERE Column1 IS NOT NULL
SELECT * FROM MASTER
WHERE (Filter = 'I' AND Column1 IS NULL)
OR
(Filter <> 'I' AND Column1 IS NOT NULL)
If you really insist on using a CASE the SELECT could be rewritten as:
SELECT *
FROM MASTER
WHERE CASE
WHEN COLUMN1 IS NULL AND FILTER = 'I' THEN 1
WHEN COLUMN1 IS NOT NULL AND FILTER <> 'I' THEN 1
ELSE 0
END = 1
SQLFiddle here
Frankly, though, I think that this is very difficult to interpret, and I suggest that #MAli's version is better.
Your case has assignment not equality check

How Do I Use Case Statement Column In Group By

As stated by the question, I'm trying to formulate a query that has a case statement in the column results, and then I want to include that column in the query's group by statement. To give a concrete example, here is all little of what my query looks like:
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
GROUP BY SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2, CASE_COLUMN
Before coming here, I checked out a few websites, including this one, to try solve my problem. I've tried adding another alias after the CASE keyword like is shown in the linked web page but have had no luck. The error message I continue to receive is the following:
[Error] Script lines: 127-151 ----------------------
CASE_COLUMN IS NOT VALID IN THE CONTEXT WHERE IT IS USED. SQLCODE=-206, SQLSTATE=42703, DRIVER=3.53.71
Has anyone else run into the issues I'm facing and been able to use a GROUP BY on the results of a CASE statement? Any help would be appreciated. Oh, and the DB2 version is a z/OS instance, version 10 (DSN10015)
The alias isn't available to use in the GROUP BY because when GROUP BY happens the alias isn't defined yet:
Here's the order:
1.FROM
2.WHERE
3.GROUP BY
4.HAVING
5.SELECT
6.ORDER BY
You can work around that with:
SELECT column1,column2,case_column
FROM (
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
) a
GROUP BY COLUMN1, COLUMN2, CASE_COLUMN
Or just use the case you use in SELECT in GROUP BY
You can either use the case as is in the group by, like this:
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
GROUP BY SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END
or use a sub-query like this:
select COLUMN1, COLUMN2, CASE_COLUMN
from (
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
) a
GROUP BY COLUMN1, COLUMN2, CASE_COLUMN

Selecting filtered rows with SQL

I am constructing an SQL statement with some parameters. Finally, an SQL statement is created like
"select * from table where column1 = "xyz"".
But I also need the rows which are filtered with this statement. In this case they're rows which are not "xyz" valued in column1. More specifically, I am looking for something like INVERSE(select * from table where ...). Is it possible?
Edit: My bad, I know I can do it with != or operator. Here the case is, select statement may be more complex (with some ANDs and equal, greater operators). Let's assume a table has A,B,C and my SQL statement brings only A as result. But I need B and C while I only have the statement which brings A.
select * from table where column1 != 'xyz' or column1 is null;
If you want the other ones, do it like this:
select * from table where column1 <> "xyz"
column1 <> (differs from) "xyz"
To check if something is no equal you can use <> or even !=
SELECT *
FROM yourTable
WHERE <> 'xyz'
OR
SELECT *
FROM yourTable
WHERE != 'xyz'
Many database vendors support (see list) both versions of the syntax.
If you're retrieving both result sets at about the same time, and just want to process the xyz ones first, you could do:
select *,CASE WHEN column1 = "xyz" THEN 1 ELSE 0 END as xyz from table
order by CASE WHEN column1 = "xyz" THEN 1 ELSE 0 END desc
This will return all of the rows in one result set. Whilst xyz = 1, these were the rows with column1 = 'xyz'.
It was :
"select * from table where rowId NOT IN (select rowId from table where column1 = "xyz")
I needed a unique rowId column to achieve this.

SQL Server 2005/2008 Group By statement with parameters without using dynamic SQL?

Is there a way to write SQL Server Stored Procedure which to be strongly typed ( i.e. returning known result set of columns ) and having its group statement to be dynamic.
Something like:
SELECT SUM( Column0 ) FROM Table1
GROUP BY #MyVar
I tried the following also:
SELECT SUM( Column0 ) FROM Table1
GROUP BY CASE #MyVar WHEN 'Column1' THEN Column1 ELSE Column2
The second statement works only in scenarios where the db types of Column1 and Column2 are the same. If they are not the SQL engine throws an error saying something similar to: "Conversion failed when converting the nvarchar value 'SYSTEM' to data type [The Different TYPE]."
What can I do to achieve strong result set and yet have some dynamic part - i.e. the grouper in my case? This will be exposed to LINQ.
EDIT:
As seems you can do it, but you should NOT! Absolutely overkill. Testing showed figures of thousand times slower execution plans. And it will only get slower with bigger result sets.
You can group on a constant which might be useful
SELECT
SUM(Column0),
CASE #MyVar WHEN 'Column1' THEN Column1 ELSE '' END AS MyGrouping
FROM
Table1
GROUP BY
CASE #MyVar WHEN 'Column1' THEN Column1 ELSE '' END
Edit: For datatype mismatch and multiple values and this allows you to group on both columns...
SELECT
SUM(Column0),
CASE #MyVar WHEN 'Column1' THEN Column1 ELSE NULL END AS Column1,
CASE #MyVar WHEN 'Column2' THEN Column2 ELSE NULL END AS Column2
FROM
Table1
GROUP BY
CASE #MyVar WHEN 'Column1' THEN Column1 ELSE NULL END,
CASE #MyVar WHEN 'Column2' THEN Column2 ELSE NULL END
You are about to shoot yourself in the foot and are asking for a bigger bullet.
The only sensible approach to this is to separate the IF into a T-SQL flow control statement:
IF (0 = #MyVar)
SELECT SUM(Column0) FROM Table1 GROUP BY Column1;
ELSE IF (1 = #MyVar)
SELECT SUM(Column0) FROM Table1 GROUP BY Column2;
ESLE IF (2 = #myVar)
SELECT SUM(Column0) FROM Table1 GROUP BY Column3;
The last thing you want from the query optimizer is to generate a plan that has to GROUP BY a condition that is determined by a variable.