SQL Server CASE statement with mupltiple conditionals syntax - sql

I have a need to add a case statement into a select, but I cannot seem to get the syntax right, could anyone help?
SELECT
uuid = pnt.ID
,extras = (CASE (SELECT pnt.TypeID as [type], pnt.Source as source)
WHEN source = 7 THEN 'a'
WHEN source = 1 AND [type] = 0 THEN 'b'
WHEN source = 8 THEN 'c'
WHEN source = 2 AND [type] = 0 THEN 'd'
WHEN source = 3 AND [type] IN (5,6,7,8) THEN 'e'
ELSE NULL
END)
FROM
Mydata as pnt
There are multiple problems, the select within the case is incorrect, the condition source = 7 is wrong, the combining conditions with an AND is wrong and the condition using IN is incorrect.
I used the answer to Multiple Criteria In Case Statement as a basis for the case statement.

SELECT
#uuid = pnt.ID
,#extras = (CASE WHEN source = 7 THEN
'a'
WHEN source = 1 AND [type] = 0 THEN
'b'
WHEN source = 8 THEN
'c'
WHEN source = 2 AND [type] =0 THEN
'd'
WHEN source = 3 AND [type] IN (5,6,7,8) THEN
'e'
ELSE NULL
END
)
FROM
Mydata as pnt

There are two types of case statements:
A simple case statement that compares an expression to a set of simple expressions to return specific values.
A searched case statement that evaluates a set of Boolean expressions to return specific values.
https://msdn.microsoft.com/en-us/library/ms144841(v=sql.105).aspx
In your script your're "mixing" them, so that your script doesn't work.
This could be a good solution:
SELECT
pnt.ID
,CASE
WHEN pnt.source = 7 THEN 'a'
WHEN pnt.source = 1 AND pnt.TypeID = 0 THEN 'b'
WHEN pnt.source = 8 THEN 'c'
WHEN pnt.source = 2 AND pnt.TypeID = 0 THEN 'd'
WHEN pnt.source = 3 AND pnt.TypeID IN (5, 6, 7, 8) THEN 'e'
ELSE NULL
END
FROM
#Mydata AS pnt
Warning!
If you need to populate single variables (uuid, extras) you have to be sure that your query's result will have only 1 record

SELECT
PNT.ID AS UUID
, CASE
WHEN PNT.source = 7 THEN 'a'
WHEN PNT.source = 1 AND PNT.[type] = 0 THEN 'b'
WHEN PNT.source = 8 THEN 'c'
WHEN PNT.source = 2 AND PNT.[type] = 0 THEN 'd'
WHEN PNT.source = 3 AND PNT.[type] IN (5, 6, 7, 8) THEN 'e'
ELSE NULL
END AS EXTRAS
FROM Mydata AS PNT
As you are already working within the table Mydata a case expression has access to the values held in [source] and [type] without an added select.
I have put the column aliases at the end of each column definition, I believe this is more generally supported by databases than using = for that purpose.

SELECT ID As uuid, CASE WHEN Source = 7 THEN
'a'
WHEN Source = 1 AND TypeID= 0 THEN
'b'
WHEN Source = 8 THEN
'c'
WHEN Source = 2 AND TypeID= 0 THEN
'd'
WHEN Source = 3 AND TypeID IN (5,6,7,8) THEN
'e'
ELSE
NULL
END
AS extras FROM Mydata

Related

change where statement given a case

I have a table which contains users info. with the columns:
id_staff
email
id_supervisor
id_branch
id_department
and I want to select the information in this table depending on a variable like
DECLARE #user_type nvarchar(20) = 'manager'
How can I change the where statement based on the variable
Example:
SELECT *
FROM users
WHERE
(
CASE WHEN #user_type = 'manager' THEN
id_branch = 3 AND id_department = 9
ELSE
id_supervisor = 15
)
Use boolean logic. You seem to want:
SELECT *
FROM users
WHERE
(#user_type = 'manager' AND id_branch = 3 AND id_department = 9)
OR (#user_type <> 'manager' AND id_supervisor = 15)
The THEN parts of CASE expressions produce values. They cannot produce futher boolean expressions. To resolve this, you must move all of the logic up to the WHEN parts of the CASE expression:
SELECT *
FROM users
WHERE 1 = CASE WHEN #User_type = 'manager' AND id_branch = 3 and id_deparment = 0
THEN 1
WHEN #user_type <> 'manager' AND id_supervisor = 15
THEN 1
ELSE 0 END
You can use case expression like this
SELECT * FROM users
WHERE 1 = CASE WHEN #user_type = 'manager'
THEN CASE WHEN id_branch = 3 AND id_department = 9
THEN 1
ELSE 0 END
WHEN id_supervisor = 15
THEN 1
ELSE 0 END

Sql query to create following tables

use the below table 1 to generate table 2
Table 1
Col1 A B C
------------------
N1 1 0 0
N2 0 1 0
N3 1 0 0
Table 2
output
new_col
-------
N1 A
N2 B
N3 A
Also how to use Table 2 to generate table 1 above
Following SQL query can be help to get requested output:
SELECT Col1,IF(A=1,'A',IF(B=1,'B','C')) AS result FROM `table_name`;
You can use conditinal with CONCAT() Function :
SELECT CONCAT(col1,' ',
CASE WHEN A = 1 THEN 'A' ELSE '' END,
CASE WHEN B = 1 THEN 'B' ELSE '' END,
CASE WHEN C = 1 THEN 'C' ELSE '' END)
FROM table1
provided you're on a DBMS with brand name such as MySQL, PostGRES, SQL Server. As an example, Oracle DB won't allow using more than two arguments for CONCAT() Function.
In order to create table2, use for most of the DBMS :
CREATE TABLE table2 AS
SELECT CONCAT(col1,' ',
CASE WHEN A = 1 THEN 'A' ELSE '' END,
CASE WHEN B = 1 THEN 'B' ELSE '' END,
CASE WHEN C = 1 THEN 'C' ELSE '' END) AS new_col
FROM table1
except for SQL Server in which prefer using :
SELECT CONCAT(col1,' ',
CASE WHEN A = 1 THEN 'A' ELSE '' END,
CASE WHEN B = 1 THEN 'B' ELSE '' END,
CASE WHEN C = 1 THEN 'C' ELSE '' END) AS new_col
INTO table2
FROM table1
In order to implement a reverse engineering(go back to original table), you need to consider the dialectics for each seperate database to handle string values. Assume you're using MySQL DB, then consider using :
CREATE TABLE table3 AS
SELECT SUBSTRING(new_col,1,instr(new_col,' ')-1) AS col1,
CASE WHEN instr(new_col,'A') > 0 THEN 1 ELSE 0 END AS A,
CASE WHEN instr(new_col,'B') > 0 THEN 1 ELSE 0 END AS B,
CASE WHEN instr(new_col,'C') > 0 THEN 1 ELSE 0 END AS C
FROM table2
where I used a different table name (table3), since table1 already exists.
Demo
Btw, if Oracle DB is the case, then use :
SELECT CONCAT(CONCAT(col1,' '),
CASE WHEN A = 1 THEN 'A' ELSE '' END||
CASE WHEN B = 1 THEN 'B' ELSE '' END||
CASE WHEN C = 1 THEN 'C' ELSE '' END) AS new_col
FROM table1
You can use one case statement. This works in Oracle.
SELECT col1
|| CASE
WHEN A = 1
THEN 'A'
WHEN B = 1
THEN 'B'
WHEN C = 1
THEN 'C'
END
NEW_COL
FROM table1
It is unclear what you want when there are multiple "1"s in a row. This is a simple solution:
select id, A from t where A = 1
union all
select id, B from t where B = 1
union all
select id, C from t where C = 1;
In databases that support lateral joins, I would recommend:
select t.id, v.which
from t cross join lateral
(values ('A', t.A), ('B', B), ('C', C)
) v(which, val)
where val = 1;

Updating column conditional on other columns

My server was crashed, damaging my database. In one of my tables I have an academic_quality column where I store school grades like A, B, C+, D. Somehow, my grades are not distributed through other columns on some rows. I thought I could create a conditional clause and create a new column, academic_quality_new, and update it after checking other columns. I tried the following query but it did not work.
SELECT academic_quality, acceptance_rate, undergrads, setting, environment, degrees_offered,
CASE WHEN (academic_quality OR acceptance_rate OR undergrads OR setting OR environment OR degrees_offered) = 'A' THEN INSERT 'A' INTO academic_quality_new
CASE WHEN (academic_quality OR acceptance_rate OR undergrads OR setting OR environment OR degrees_offered) = 'C' THEN INSERT 'B' INTO academic_quality_new
FROM [school_List_V4]
Any help would be appreciated!
You can try by adding case..when for all available grades.
First you can execute select query and check result
select * ,
case when academic_quality = 'A' OR acceptance_rate = 'A' then 'A'
else case when academic_quality ='B' OR acceptance_rate = 'B' then 'B'
else case when academic_quality = 'C' OR acceptance_rate = 'C' then 'C'
else '--'
end
end
end
from table1
then try this update query, it will update new column. If 2 cases are true then it will take first case, so case on grades should be from highest to lowest.
update table1
set new =
case when academic_quality = 'A' OR acceptance_rate = 'A' then 'A'
else case when academic_quality ='B' OR acceptance_rate = 'B' then 'B'
else case when academic_quality = 'C' OR acceptance_rate = 'C' then 'C'
else '--'
end
end
end
and final updated new column is select * from table1
academic_quality | acceptance_rate | new
A | NULL | A
NULL | B | B
NULL | NULL | --
A | B | A
C | B | B

Replacing CASE in SQL query

I got three columns with binary values. Then i got a query which makes a string based on those values. I made this work using case. But it's quite huge (it's a part of a bigger query), and i was wondering maybe there is a better way of doing this?
SELECT (CASE
WHEN TableA.flag1 = 1 AND TableA.flag2 = 1 AND TableA.flag3 = 1 THEN 'CGR'
WHEN TableA.flag1 = 1 AND TableA.flag2 = 1 THEN 'CG'
WHEN TableA.flag1 = 1 AND TableA.flag3 = 1 THEN 'CR'
WHEN TableA.flag2 = 1 AND TableA.flag3 = 1 THEN 'GR'
WHEN TableA.flag1 = 1 THEN 'C'
WHEN TableA.flag2 = 1 THEN 'G'
WHEN TableA.flag3 = 1 THEN 'R'
ELSE 'nothing'
END)
FROM TableA
Im working on MSSQL 2000 server.
You can use left() instead.
select left('C', T.flag1)+
left('G', T.flag2)+
left('R', T.flag3)
from TableA as T
I don't know if this is "better" but it is more concise:
SELECT ((CASE WHEN TableA.flag1 = 1 THEN 'C' ELSE '' END) +
(CASE WHEN TableA.flag2 = 1 THEN 'G' ELSE '' END) +
(CASE WHEN TableA.flag3 = 1 THEN 'R' ELSE '' END)
)
FROM TableA;
Okay, this isn't exactly the same because you get '' instead of 'nothing'. But I think the empty string does a better job of representing "no flags" than 'nothing' does.
Try this:
SELECT
CASE WHEN flag1 = 1 THEN 'C' ELSE '' END +
CASE WHEN flag2 = 1 THEN 'G' ELSE '' END +
CASE WHEN flag3 = 1 THEN 'R' ELSE '' END
FROM TABLEA
Maybe you could use function and move this CASE statement to this function

counting records on the same table with different values possibly none sql server 2008

I have a inventory table with a condition i.e. new, used, other, and i am query a small set of this data, and there is a possibility that all the record set contains only 1 or all the conditions. I tried using a case statement, but if one of the conditions isn't found nothing for that condition returned, and I need it to return 0
This is what I've tried so far:
select(
case
when new_used = 'N' then 'new'
when new_used = 'U' then 'used'
when new_used = 'O' then 'other'
end
)as conditions,
count(*) as count
from myDB
where something = something
group by(
case
when New_Used = 'N' then 'new'
when New_Used = 'U' then 'used'
when New_Used = 'O' then 'other'
end
)
This returns the data like:
conditions | count
------------------
new 10
used 45
I am trying to get the data to return like the following:
conditions | count
------------------
new | 10
used | 45
other | 0
Thanks in advance
;WITH constants(letter,word) AS
(
SELECT l,w FROM (VALUES('N','new'),('U','used'),('O','other')) AS x(l,w)
)
SELECT
conditions = c.word,
[count] = COUNT(x.new_used)
FROM constants AS c
LEFT OUTER JOIN dbo.myDB AS x
ON c.letter = x.new_used
AND something = something
GROUP BY c.word;
try this -
DECLARE #t TABLE (new_used CHAR(1))
INSERT INTO #t (new_used)
SELECT t = 'N'
UNION ALL
SELECT 'N'
UNION ALL
SELECT 'U'
SELECT conditions, ISNULL(r.cnt, 0) AS [count]
FROM (
VALUES('U', 'used'), ('N', 'new'), ('O', 'other')
) t(c, conditions)
LEFT JOIN (
SELECT new_used, COUNT(1) AS cnt
FROM #t
--WHERE something = something
GROUP BY new_used
) r ON r.new_used = t.c
in output -
new 2
used 1
other 0
You can do it as a cross-tab:
select
sum(case when new_used = 'N' then 1 else 0 end) as N,
sum(case when new_used = 'U' then 1 else 0 end) as U,
sum(case when new_used = 'O' then 1 else 0 end) as Other
from myDB
where something = something