change where statement given a case - sql

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

Related

Simple way to check % of total if I add one criteria

I have the following script:
select count (*)
from somewhere
where 1=1
and criteria 1 = 'xxx'
and criteria 2 = 'xx'
and criteria 3 = 'x'
Is there a nice way to calculate the % of the count with the first 2 criterias vs the count with all 3 criterias ?
So far I'm using something that is not very elegant:
Select x.nb / y.nb
from
(select count (*) as nb
from somewhere
where 1=1
and criteria 1 = 'xxx'
and criteria 2 = 'xx'
and criteria 3 = 'x' ) x
JOIN
(select count (*) as nb
from somewhere
where 1=1
and criteria 1 = 'xxx'
and criteria 2 = 'xx' ) y on 1 = 1
Thanks!
You can use avg():
select avg(case when criteria3 = 'x' then 1.0 else 0 end) as ratio
from somewhere
where criteria 1 = 'xxx' and criteria 2 = 'xx' ;
Or more concisely as:
select avg( (criteria3 = 'x')::int ) as ratio
from somewhere
where criteria 1 = 'xxx' and criteria 2 = 'xx' ;

Using Nested Case Expression

I am stuck in properly using Nested Case Expression.
The requirement is to create the calculated column that will be either 0 or 1.
If the name is 'abc' and ind = 1, then the value of calc column will be 1 . But if the name is 'abc' and salary is > 2000 . then the value will be 1 again irrespective the value of ind.
I have written the below query using OR condition in CASE Expression but want to use the Nested CASE.
select t.*, case when (name = 'abc' and ind = 1 ) or (name = 'abc' and sal > 2000)
then 1
else 0
end
from test t
Below is the result:
You don't need nested CASE:
-- multiple conditions
select t.*, case when name = 'abc' and ind = 1 then 1
when name = 'abc' and sal > 2000 then 1
else 0 end
from test t
I don't know why you need nested case expression, i would do instead of nested case expression that would be more efficient :
select t.*, (case when name = 'abc' and (ind = 1 or sal > 2000)
then 1
else 0
end)
from test t;
If you HAVE to have nested case expression then this is how you would write it:
SELECT t.*,
CASE
WHEN name = 'abc' THEN
CASE
WHEN ind = 1 THEN 1
WHEN sal > 2000 THEN 1
ELSE 0
END
ELSE 0
END
FROM test t;
If you are on SQL Server 2012 and above, you can also use an IIF statement like below:
select iif(name = 'abc' AND (salary > 2000 OR ind = 1), 1,0)

combining boolean results from two columns SQL

I have the following example data from two Boolean columns:
ID Male Female
1 1 0
2 0 1
3 0 1
4 1 0
5 0 1
I would like to combine the two columns into a single column containing just 'M' and 'F'. Also, I would preferably like to do it in the SELECT statement I am writing while defining the column.
The result then should be something like:
ID Gender
1 M
2 F
3 F
4 M
5 F
I know I could achieve this with separate update statements like:
UPDATE table_1
SET Gender='M'
FROM table_2 t2
WHERE t2.Male=1
and
UPDATE table_1
SET Gender='F'
FROM table_2 t2
WHERE t2.Female=1
But I was really hoping to achieve the same result while declaring the Gender column?
Does anyone know if this is possible?
Thanks in advance!
You can use a CASE expression.
Query
UPDATE t1
SET t1.Gender = (
CASE WHEN t2.Male = 1 AND t2.Female = 0 THEN 'M'
WHEN t2.Male = 0 AND t2.Female = 1 THEN 'F'
ELSE NULL END
)
FROM Table_1 t1
JOIN Table_2 t2
ON t1.ID = t2.ID;
UPDATE table_1
SET Gender= CASE WHEN Male = 1 THEN 'M'
WHEN Female = 1 THEN 'F'
ELSE 'Other' // optional
END;
Of course im trying to be open mind and guess you allow Male = 0 and Female = 0
otherwise you can simplify with IIF
UPDATE table_1
SET Gender = IIF ( Male = 1, 'M', 'F' );
Here is how to do it with a SELECT statement:
SELECT ID,
CASE WHEN Male = 1 THEN 'M'
ELSE 'F' END AS gender
FROM My_Table
How about select if(Male = 1, 'M', 'F') as gender?

SQL Server CASE statement with mupltiple conditionals syntax

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

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