SQL return multiple values from CASE statement - sql

How do I rewrite this SQL statement to do what I need?
SELECT * FROM TABLE
WHERE COLUMN_NAME_1 IN (CASE
WHEN COLUMN_NAME_2 = 'X' THEN 'A'
WHEN COLUMN_NAME_2 = 'Y' THEN 'B', 'C' END)
Obviously I can't return multiple values from a CASE clause... so how else could I write this? I am pretty sure I am slow today because this seems so easy ....

SELECT * FROM Table WHERE
(COLUMN_NAME_2 = 'X' AND COLUMN_NAME_1 = 'A') OR
(COLUMN_NAME_2 = 'Y' AND COLUMN_NAME_1 IN ('B', 'C'))
or
SELECT * FROM Table WHERE COLUMN_NAME_2 = 'X' AND COLUMN_NAME_1 = 'A'
UNION ALL
SELECT * FROM Table WHERE COLUMN_NAME_2 = 'Y' AND COLUMN_NAME_1 IN ('B', 'C')
This presumes that you only want results with X or Y in COLUMN_NAME_2. If you want other rows it's not possible to tell which ones from your original SQL.

Related

PL/SQL Case When - Map input to other column values

I've checked elsewhere on Stack but I couldn't find a similar scenario.
I want to essentially map 1 input from a PL/SQL procedure to 3 different values in MY_TABLE; otherwise I just want to filter on the input. I would like a solution similar to the below pseudocode
SELECT * FROM MY_TABLE
WHERE COLUMN 1 = 'B'
AND CASE WHEN p_input = 'F' THEN COLUMN_1 IN ('F','A','B')
ELSE COLUMN_1 = p_input;
I don't recommend using case expressions in the where. Just use simpler boolean logic operators:
WHERE COLUMN 1 = 'B' AND
( (p_input = 'F' AND COLUMN_1 IN ('F', 'A', 'B')) OR
COLUMN_1 = p_input
)
In particular, Oracle doesn't have a boolean type in SQL (there is on in PL/SQL). So a case expression cannot return a boolean value.
If you are learning how to use case..when in where clause then following is the code:
CASE WHEN p_input = 'F' AND COLUMN_1 IN ('F','A','B') THEN 1
WHEN COLUMN_1 = p_input THEN 1
END = 1
But as suggested in other answer, it is recomended to use or And it is always a good idea to use negative condition p_input <> 'F' in second condition while using OR as follows:
(
(p_input = 'F' AND COLUMN_1 IN ('F', 'A', 'B'))
OR
(p_input <> 'F' AND COLUMN_1 = p_input)
)

simplify multiple union in sql

i am trying to simply the following union query .Basically i am trying to get all the possible values from same table different column and i have to take value which are not equal to no then replace them with specific text when they are from respective column.
select 'a' from Mytable where a!='no' and id='1'
union
select 'b' from Mytable where b!='no' and id='1'
union select 'c' from Mytable where c!='no' and id='1'
so my table structure will be
id Acolumn BColumn Ccolumn
1 123a no 345v
so my expected result is
a c
so please suggest me to simplify this query thanks in advance
According to what you've written, this might be OK.
select case when a <> 'no' and id = '1' then 'a'
when b <> 'no' and id = '1' then 'b'
when c <> 'no' and id = '1' then 'c'
end
from mytable
where (a <> 'no' and id = '1')
or (b <> 'no' and id = '1')
or (c <> 'no' and id = '1')

sql server select where case IN

Please help with syntax, i need where IN clause only when parameter = 1 otherwise all records
not working
SELECT * FROM T
WHERE T.C = 'AAA'
AND CASE WHEN #Param = 1 THEN T.ID IN ('1','2','3') END - this condition only needed when #param = 1
Im try below, but how get all records?
AND T.ID IN CASE WHEN #Param = 1 THEN ('1','2','3') ELSE -all rows- END
Don't use CASE for this.
Rewrite your SQL like this:
WHERE
T.C = 'AAA'
AND (
(#Param = 1 AND T.ID IN ('1', '2', '3'))
OR
(#Param <> 1)
)
Remove whitespace as needed when you understand how/why it works.
It can even be shortened down if we change the order of the OR part (not necessary really but easier to understand for us humans then):
WHERE
T.C = 'AAA'
AND (
#Param <> 1
OR
T.ID IN ('1', '2', '3')
)
If #Param is not different from 1, it has to be 1, so then you don't need to explicitly check this in the other branch.
Thus the best way to do this is this:
WHERE
T.C = 'AAA'
AND (#Param <> 1 OR T.ID IN ('1', '2', '3'))

How do I build this simple mySQL query?

I would like to select all rows where field A is 'x' and field B is one of 'w', 'y' or 'z'.
A and B are both strings, and I would like case to be ignored.
SELECT *
FROM table
WHERE LOWER(A) = 'x'
AND LOWER(B) IN ('w', 'y', 'z')
select * from tablename where LCASE(A) ='x' and LCASE(B) in('w','y','z')
I would like to select all rows where field A is 'x' and field B is one of 'w', 'y' or 'z'
... WHERE fldA = "x" AND fldB IN ("w", "y", "z") ...
A and B are both strings, and I would like case to be ignored.
Just make sure that columns' collations are set to case insensitive type, eg utf8_unicode_ci, utf8_german_ci, latin2_general_ci (the suffix _ci is the key).

How do I perform an IF...THEN in an SQL SELECT?

How do I perform an IF...THEN in an SQL SELECT statement?
For example:
SELECT IF(Obsolete = 'N' OR InStock = 'Y' ? 1 : 0) AS Saleable, * FROM Product
The CASE statement is the closest to IF in SQL and is supported on all versions of SQL Server.
SELECT CAST(
CASE
WHEN Obsolete = 'N' or InStock = 'Y'
THEN 1
ELSE 0
END AS bit) as Saleable, *
FROM Product
You only need to use the CAST operator if you want the result as a Boolean value. If you are happy with an int, this works:
SELECT CASE
WHEN Obsolete = 'N' or InStock = 'Y'
THEN 1
ELSE 0
END as Saleable, *
FROM Product
CASE statements can be embedded in other CASE statements and even included in aggregates.
SQL Server Denali (SQL Server 2012) adds the IIF statement which is also available in access (pointed out by Martin Smith):
SELECT IIF(Obsolete = 'N' or InStock = 'Y', 1, 0) as Saleable, * FROM Product
The case statement is your friend in this situation, and takes one of two forms:
The simple case:
SELECT CASE <variable> WHEN <value> THEN <returnvalue>
WHEN <othervalue> THEN <returnthis>
ELSE <returndefaultcase>
END AS <newcolumnname>
FROM <table>
The extended case:
SELECT CASE WHEN <test> THEN <returnvalue>
WHEN <othertest> THEN <returnthis>
ELSE <returndefaultcase>
END AS <newcolumnname>
FROM <table>
You can even put case statements in an order by clause for really fancy ordering.
From SQL Server 2012 you can use the IIF function for this.
SELECT IIF(Obsolete = 'N' OR InStock = 'Y', 1, 0) AS Salable, *
FROM Product
This is effectively just a shorthand (albeit not standard SQL) way of writing CASE.
I prefer the conciseness when compared with the expanded CASE version.
Both IIF() and CASE resolve as expressions within a SQL statement and can only be used in well-defined places.
The CASE expression cannot be used to control the flow of execution of
Transact-SQL statements, statement blocks, user-defined functions, and
stored procedures.
If your needs can not be satisfied by these limitations (for example, a need to return differently shaped result sets dependent on some condition) then SQL Server does also have a procedural IF keyword.
IF #IncludeExtendedInformation = 1
BEGIN
SELECT A,B,C,X,Y,Z
FROM T
END
ELSE
BEGIN
SELECT A,B,C
FROM T
END
Care must sometimes be taken to avoid parameter sniffing issues with this approach however.
You can find some nice examples in The Power of SQL CASE Statements, and I think the statement that you can use will be something like this (from 4guysfromrolla):
SELECT
FirstName, LastName,
Salary, DOB,
CASE Gender
WHEN 'M' THEN 'Male'
WHEN 'F' THEN 'Female'
END
FROM Employees
Use CASE. Something like this.
SELECT Salable =
CASE Obsolete
WHEN 'N' THEN 1
ELSE 0
END
SELECT
(CASE
WHEN (Obsolete = 'N' OR InStock = 'Y') THEN 'YES'
ELSE 'NO'
END) as Salable
, *
FROM Product
Microsoft SQL Server (T-SQL)
In a select, use:
select case when Obsolete = 'N' or InStock = 'Y' then 'YES' else 'NO' end
In a where clause, use:
where 1 = case when Obsolete = 'N' or InStock = 'Y' then 1 else 0 end
From this link, we can understand IF THEN ELSE in T-SQL:
IF EXISTS(SELECT *
FROM Northwind.dbo.Customers
WHERE CustomerId = 'ALFKI')
PRINT 'Need to update Customer Record ALFKI'
ELSE
PRINT 'Need to add Customer Record ALFKI'
IF EXISTS(SELECT *
FROM Northwind.dbo.Customers
WHERE CustomerId = 'LARSE')
PRINT 'Need to update Customer Record LARSE'
ELSE
PRINT 'Need to add Customer Record LARSE'
Isn't this good enough for T-SQL?
SELECT
CASE
WHEN OBSOLETE = 'N' or InStock = 'Y' THEN 'TRUE'
ELSE 'FALSE'
END AS Salable,
*
FROM PRODUCT
Simple if-else statement in SQL Server:
DECLARE #val INT;
SET #val = 15;
IF #val < 25
PRINT 'Hi Ravi Anand';
ELSE
PRINT 'By Ravi Anand.';
GO
Nested If...else statement in SQL Server -
DECLARE #val INT;
SET #val = 15;
IF #val < 25
PRINT 'Hi Ravi Anand.';
ELSE
BEGIN
IF #val < 50
PRINT 'what''s up?';
ELSE
PRINT 'Bye Ravi Anand.';
END;
GO
Use a CASE statement:
SELECT CASE
WHEN (Obsolete = 'N' OR InStock = 'Y')
THEN 'Y'
ELSE 'N'
END as Available
etc...
A new feature, IIF (that we can simply use), was added in SQL Server 2012:
SELECT IIF ( (Obsolete = 'N' OR InStock = 'Y'), 1, 0) AS Saleable, * FROM Product
Use pure bit logic:
DECLARE #Product TABLE (
id INT PRIMARY KEY IDENTITY NOT NULL
,Obsolote CHAR(1)
,Instock CHAR(1)
)
INSERT INTO #Product ([Obsolote], [Instock])
VALUES ('N', 'N'), ('N', 'Y'), ('Y', 'Y'), ('Y', 'N')
;
WITH cte
AS
(
SELECT
'CheckIfInstock' = CAST(ISNULL(NULLIF(ISNULL(NULLIF(p.[Instock], 'Y'), 1), 'N'), 0) AS BIT)
,'CheckIfObsolote' = CAST(ISNULL(NULLIF(ISNULL(NULLIF(p.[Obsolote], 'N'), 0), 'Y'), 1) AS BIT)
,*
FROM
#Product AS p
)
SELECT
'Salable' = c.[CheckIfInstock] & ~c.[CheckIfObsolote]
,*
FROM
[cte] c
See working demo: if then without case in SQL Server.
For start, you need to work out the value of true and false for selected conditions. Here comes two NULLIF:
for true: ISNULL(NULLIF(p.[Instock], 'Y'), 1)
for false: ISNULL(NULLIF(p.[Instock], 'N'), 0)
combined together gives 1 or 0. Next use bitwise operators.
It's the most WYSIWYG method.
SELECT 1 AS Saleable, *
FROM #Product
WHERE ( Obsolete = 'N' OR InStock = 'Y' )
UNION
SELECT 0 AS Saleable, *
FROM #Product
WHERE NOT ( Obsolete = 'N' OR InStock = 'Y' )
SELECT CASE WHEN profile.nrefillno = 0 THEN 'N' ELSE 'R'END as newref
From profile
case statement some what similar to if in SQL server
SELECT CASE
WHEN Obsolete = 'N' or InStock = 'Y'
THEN 1
ELSE 0
END as Saleable, *
FROM Product
This isn't an answer, just an example of a CASE statement in use where I work. It has a nested CASE statement. Now you know why my eyes are crossed.
CASE orweb2.dbo.Inventory.RegulatingAgencyName
WHEN 'Region 1'
THEN orweb2.dbo.CountyStateAgContactInfo.ContactState
WHEN 'Region 2'
THEN orweb2.dbo.CountyStateAgContactInfo.ContactState
WHEN 'Region 3'
THEN orweb2.dbo.CountyStateAgContactInfo.ContactState
WHEN 'DEPT OF AGRICULTURE'
THEN orweb2.dbo.CountyStateAgContactInfo.ContactAg
ELSE (
CASE orweb2.dbo.CountyStateAgContactInfo.IsContract
WHEN 1
THEN orweb2.dbo.CountyStateAgContactInfo.ContactCounty
ELSE orweb2.dbo.CountyStateAgContactInfo.ContactState
END
)
END AS [County Contact Name]
If you're inserting results into a table for the first time, rather than transferring results from one table to another, this works in Oracle 11.2g:
INSERT INTO customers (last_name, first_name, city)
SELECT 'Doe', 'John', 'Chicago' FROM dual
WHERE NOT EXISTS
(SELECT '1' from customers
where last_name = 'Doe'
and first_name = 'John'
and city = 'Chicago');
As an alternative solution to the CASE statement, a table-driven approach can be used:
DECLARE #Product TABLE (ID INT, Obsolete VARCHAR(10), InStock VARCHAR(10))
INSERT INTO #Product VALUES
(1,'N','Y'),
(2,'A','B'),
(3,'N','B'),
(4,'A','Y')
SELECT P.* , ISNULL(Stmt.Saleable,0) Saleable
FROM
#Product P
LEFT JOIN
( VALUES
( 'N', 'Y', 1 )
) Stmt (Obsolete, InStock, Saleable)
ON P.InStock = Stmt.InStock OR P.Obsolete = Stmt.Obsolete
Result:
ID Obsolete InStock Saleable
----------- ---------- ---------- -----------
1 N Y 1
2 A B 0
3 N B 1
4 A Y 1
SELECT CASE WHEN Obsolete = 'N' or InStock = 'Y' THEN 1 ELSE 0
END AS Saleable, *
FROM Product
You can have two choices for this to actually implement:
Using IIF, which got introduced from SQL Server 2012:
SELECT IIF ( (Obsolete = 'N' OR InStock = 'Y'), 1, 0) AS Saleable, * FROM Product
Using Select Case:
SELECT CASE
WHEN Obsolete = 'N' or InStock = 'Y'
THEN 1
ELSE 0
END as Saleable, *
FROM Product
Using SQL CASE is just like normal If / Else statements.
In the below query, if obsolete value = 'N' or if InStock value = 'Y' then the output will be 1. Otherwise the output will be 0.
Then we put that 0 or 1 value under the Salable Column.
SELECT
CASE
WHEN obsolete = 'N' OR InStock = 'Y'
THEN 1
ELSE 0
END AS Salable
, *
FROM PRODUCT
Question:
SELECT IF(Obsolete = 'N' OR InStock = 'Y' ? 1 : 0) AS Saleable, * FROM Product
ANSI:
Select
case when p.Obsolete = 'N'
or p.InStock = 'Y' then 1 else 0 end as Saleable,
p.*
FROM
Product p;
Using aliases -- p in this case -- will help prevent issues.
SELECT
if((obsolete = 'N' OR instock = 'Y'), 1, 0) AS saleable, *
FROM
product;
For those who uses SQL Server 2012, IIF is a feature that has been added and works as an alternative to Case statements.
SELECT IIF(Obsolete = 'N' OR InStock = 'Y', 1, 0) AS Salable, *
FROM Product
It will be something like that:
SELECT OrderID, Quantity,
CASE
WHEN Quantity > 30 THEN "The quantity is greater than 30"
WHEN Quantity = 30 THEN "The quantity is 30"
ELSE "The quantity is under 30"
END AS QuantityText
FROM OrderDetails;
I like the use of the CASE statements, but the question asked for an IF statement in the SQL Select. What I've used in the past has been:
SELECT
if(GENDER = "M","Male","Female") as Gender
FROM ...
It's like the Excel or sheets IF statements where there is a conditional followed by the true condition and then the false condition:
if(condition, true, false)
Furthermore, you can nest the if statements (but then use should use a CASE :-)
(Note: this works in MySQL Workbench, but it may not work on other platforms)
For the sake of completeness, I would add that SQL uses three-valued logic. The expression:
obsolete = 'N' OR instock = 'Y'
Could produce three distinct results:
| obsolete | instock | saleable |
|----------|---------|----------|
| Y | Y | true |
| Y | N | false |
| Y | null | null |
| N | Y | true |
| N | N | true |
| N | null | true |
| null | Y | true |
| null | N | null |
| null | null | null |
So for example if a product is obsolete but you dont know if product is instock then you dont know if product is saleable. You can write this three-valued logic as follows:
SELECT CASE
WHEN obsolete = 'N' OR instock = 'Y' THEN 'true'
WHEN NOT (obsolete = 'N' OR instock = 'Y') THEN 'false'
ELSE NULL
END AS saleable
Once you figure out how it works, you can convert three results to two results by deciding the behavior of null. E.g. this would treat null as not saleable:
SELECT CASE
WHEN obsolete = 'N' OR instock = 'Y' THEN 'true'
ELSE 'false' -- either false or null
END AS saleable
There are multiple conditions.
SELECT
(CASE
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1001' THEN 'DM'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1002' THEN 'GS'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1003' THEN 'MB'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1004' THEN 'MP'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1005' THEN 'PL'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1008' THEN 'DM-27'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1011' THEN 'PB'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1012' THEN 'UT-2'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1013' THEN 'JGC'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1014' THEN 'SB'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1015' THEN 'IR'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1016' THEN 'UT-3'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1017' THEN 'UT-4'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1019' THEN 'KR'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1020' THEN 'SYB-SB'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1021' THEN 'GR'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1022' THEN 'SYB-KP'
WHEN RIGHT((LEFT(POSID,5)),4) LIKE '1026' THEN 'BNS'
ELSE ''
END) AS OUTLET
FROM matrixcrm.Transact