Case statement with end = 1 in T/SQL query - sql-server

I'm hoping somebody can explain the below query to me as I'm not familiar with the syntax:
#[user1] int,
#[user2] varchar(10)
delete
from [table name]
where [id] in (select [id]
from [a diff table name]
where [user1] = #[user1])
and (case
when [user2] = 'some string' then 1
when [table field] = #user2 then 1
else 0
end) = 1
and [other field] = 0
and [other field] = 0
and [other field]= 0
Firstly, I've obviously changed all variable/table names. Apologies if anything isn't clear. I get that the first part is a delete statement where it uses an in statement. That's fine. I also get the last part, with the multiple AND statements adding conditions to the WHERE clause.
It's the case statement I'm struggling with. I've two questions.
What is the else 0 for? Is that attached to the when clause above it, so that if [table field] doesn't = the user2 variable passed in it is set to 0?
What is the end = 1? I've tried googling but haven't found any examples of this form before.

ELSE 0 means that the CASE statement will return 0 if neither of the WHEN statements are matched.
End = 1 is easier to understand if you think of it as
WHERE (CASE .... END) = 1

Your CASE stmt will return either 1 or 0 depends on data in that column.
IF it return 1 then 1=1 and other conditions which specified below will also happen.
IF it return 0 then 0=1 , Remaining conditions won't be considered.

Related

Set all column values based on condition existing in one row using Snowflake

Working on a view in Snowflake and based certain criteria I want to set the Pass/Fail column for all rows to "Pass" if a certain output is reached. Example (below)for a give Item number/ Plant combination, where the condition is met for one row, I would like to set all rows to "Pass"
Here is my case statement as is: I'm Having trouble getting this scenario to "Pass" for all rows
case
when
((case
when 'PIRStatus' is null
then 'PIR-Missing'
else 'PIR-Exists'
end)='PIR-Exists'
and "FixedVendor" = 'X'
and (case
when "SLStatus" = 'SL-Exists'
then 1
else 2
end) = 1)
then 'Pass'
else 'Fail'
end as "Pass/Fail"
PIRStatus Vendor BlockedVendor FixedVendor SLStatus Pass/Fail
PIR-Exists 12547 X SL-Exists Pass
PIR-Exists 85996 SL-Missing Fail
PIR-Exists 54788 SL-Missing Fail
This is based on a given Item/ Plant combination, as long as any row says pass then I want the other rows to Pass as well
You probably want to use a correlated subquery, which I find is best written with a CTE like this:
WITH CTE_CONDITION AS (
SELECT
id,
case when (
(
case when 'PIRStatus' is null then 'PIR-Missing' else 'PIR-Exists' end
)= 'PIR-Exists'
and "FixedVendor" = 'X'
and (
case when "SLStatus" = 'SL-Exists' then 1 else 2 end
) = 1
) then 'Pass' else 'Fail' end as "Pass/Fail"
FROM
table
)
SELECT
* ,
CASE WHEN EXISTS (SELECT 1 FROM CTE_CONDITION WHERE "Pass/Fail" = 'Pass' AND table.id = CTE_CONDITION.id)
THEN 'This ID Passes At Least Somewhere'
ELSE 'This ID never passes'
END as DOES_THIS_EVER_PASS
FROM table
The thing to remember using EXISTS is that the SELECT portion doesn't really matter (thus, SELECT 1) but it is the WHERE clause that connects the table itself to CTE_CONDITION.
You might even clean this up by creating CTE_PASS and CTE_FAIL and putting conditions in the WHERE clauses, to compartmentalize the logic and avoid that messy CASE statement.
Thus, you could accomplish the same thing with something like:
WITH CTE_PASS AS (
SELECT id
FROM table
WHERE {conditions that mean a pass}
)
SELECT
* ,
CASE WHEN EXISTS (SELECT 1 FROM CTE_PASS WHERE table.id = CTE_CONDITION.id)
THEN 'This ID Passes At Least Somewhere'
ELSE 'This ID never passes'
END as DOES_THIS_EVER_PASS
FROM table

CAN THE COUNT FUNCTION IN SQL SERVER DB ACCEPT MULTIPLE VALUES

I am querying the very popular AdventureWorks DB in SSMS.
My objective to find the number of males and females under each job title from HumanResources.Employee.
For this my original query was,
SELECT JobTitle,
COUNT(CASE WHEN Gender='M' THEN 1
ELSE 0
END) AS MALE_COUNT,
COUNT(CASE WHEN Gender='F' THEN 1
ELSE 0
END) AS FEMALE_COUNT,Gender
FROM HumanResources.Employee
GROUP BY JobTitle,Gender
ORDER BY JobTitle
GO
However, I am getting incorrect answer with the above query.So by modifying it as below ,I am getting the desired result:
SELECT JobTitle,
COUNT(CASE WHEN Gender='M' THEN 1
END) AS MALE_COUNT,
COUNT(CASE WHEN Gender='F' THEN 1
END) AS FEMALE_COUNT,Gender
FROM HumanResources.Employee
GROUP BY JobTitle,Gender
ORDER BY JobTitle
GO
As can be easily seen, I am just removing the 'ELSE 0' condition for both the CASE statements, but am I unable to figure out as to how '0' is affecting the values returned in the result.
Can someone explain to me the difference between these two? Also I would like to know how the COUNT function is taking multiple values, when normally(say SELECT COUNT(3,3)) it doesn't work.
You want SUM(), not COUNT(): the latter takes in account every non-null value (this includes 0), so your current conditional expressions counts all rows - it is equivalent to COUNT(*)
Also, I suspect that gender should probably not appear in the SELECT and GROUP BY clauses, since that's precisely what you are trying to aggregate
I think that you want:
SELECT
JobTitle,
SUM(CASE WHEN Gender='M' THEN 1 ELSE 0 END) AS MALE_COUNT,
SUM(CASE WHEN Gender='F' THEN 1 ELSE 0 END) AS FEMALE_COUNT
FROM HumanResources.Employee
GROUP BY JobTitle
ORDER BY JobTitle
Documentations say:
COUNT(ALL expression) evaluates expression for each row in a group,
and returns the number of nonnull values.
Read more here: https://learn.microsoft.com/en-us/sql/t-sql/functions/count-transact-sql?view=sql-server-ver15
So we can rewrite your query as:
SELECT
JobTitle,
COUNT(CASE WHEN Gender='M' THEN 1 ELSE NULL END) AS MALE_COUNT,
COUNT(CASE WHEN Gender='F' THEN 1 ELSE NULL END) AS FEMALE_COUNT
FROM HumanResources.Employee
GROUP BY JobTitle
ORDER BY JobTitle
About your queries:
First query:
inside Count function you have a CASE expression which will change the 'M' to 1 and 'F' to 0. Then COUNT function will do the count operations over them. because neither 1 nor 0 are NULL so Count will return total number of records, regardless of 'M' or 'F'
This procedure is same for second CASE too.
Second query:
Inside Count function you have a CASE expression which will change 'M' to 1, but you did not mentioned what to do with other values, so NULL will be returned for non-M values. After that Count function will do the count operations on these records and will return the number of M's.(Second query is equal to the query I have posted, and they both will have the same output. However because of readability I prefer my query over yours :-) )
This procedure is same for second CASE too.
Documentations for CASE expression says:
ELSE else_result_expression Is the expression returned if no
comparison operation evaluates to TRUE. If this argument is omitted
and no comparison operation evaluates to TRUE, CASE returns NULL.
else_result_expression is any valid expression. The data types of
else_result_expression and any result_expression must be the same or
must be an implicit conversion.
Read more here: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql?view=sql-server-ver15
SELECT Count(3,3)
This is syntactically wrong and will give you an error like this, which is pretty self explanatory:
Msg 174, Level 15, State 1, Line 1 The Count function requires 1
argument(s)
The syntax for Count function based on the aforementioned documentations is like this:
-- Aggregation Function Syntax
COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } )
-- Analytic Function Syntax
COUNT ( [ ALL ] { expression | * } ) OVER ( [ <partition_by_clause> ] )

Iff condition Access to SQL syntax

I have an access query that I have recreate in SQL.
Access:
SELECT Columns ,
IIf([Col1]="X",IIf([COL2]<>"XXXX",1,0)) AS NEWCOL1,
IIf([COL2] Not In ("HHH","GGG"),1,0) AS [NEWCOL2],
IIf(([NEWCOL1]=1) Or ([NEWCOL2]=1),1,0) AS NEWCOL3
FROM [TABLE]
WHERE ((([TABLE].COL2)<>"XXXX")) OR ((([TABLE].COL2)<>"HHH" And ([TABLE].COL2)<>"GGG"));
In SQL :
SELECT Columns ,
"NEWCOL1" =
CASE WHEN ([COL1]='X' AND COL2<> 'XXXX') THEN 1
ELSE 0
END,
"NEWCOL2" =
CASE WHEN COL2 NOT IN ('HHH','GGG') THEN 1
ELSE 0
END ,
IIf(([NEWCOL1]=1) Or ([NEWCOL2]=1),1,0) AS NEWCOL3
FROM [TABLE]
WHERE ((([TABLE].COL2)<>'XXXX')) OR ((([TABLE].COL2)<>'HHH' And ([TABLE].COL2)<>'GGG'));
IIf(([NEWCOL1]=1) Or ([NEWCOL2]=1),1,0) AS NEWCOL3
When I use the Newcol1 and newcol2 it throws an error invalid column how could use them maybe in a nested case or iif statement
If you're in SQL 2012, where IIF() is valid, then it looks like the problem is that you don't have an ELSE value for the first outer case:
IIf([Col1]='X',IIf([COL2]<>'XXXX',1,0){,NEED SOME ELSE VALUE HERE}) AS NEWCOL1,
I don't know why this would work in Access. I guess Access must be more "dummy proof" than SQL Server.
To replace your original first IIF with a CASE, you would do this:
CASE WHEN [Col1]='X' THEN
CASE WHEN [COL2]<>'XXXX' THEN 1 ELSE 0 END
END
By not supplying an ELSE for the first condition, if [Col1] does not equal 'X', the statement will return NULL without raising an error.
To handle your most recent request with a CTE, you could do as below:
WITH cte AS (
SELECT
Columns,
CASE WHEN ([COL1]='X' AND COL2<> 'XXXX') THEN 1 ELSE 0 END AS NEWCOL1,
CASE WHEN COL2 NOT IN ('HHH','GGG') THEN 1 ELSE 0 END AS NEWCOL2
FROM [TABLE]
WHERE ((([TABLE].COL2)<>'XXXX')) OR ((([TABLE].COL2)<>'HHH' And ([TABLE].COL2)<>'GGG'))
)
SELECT *, IIf(([NEWCOL1]=1) Or ([NEWCOL2]=1),1,0) AS NEWCOL3
FROM cte;

Aggregate Function Error on an Expression

What could be wrong with this query:
SELECT
SUM(CASE
WHEN (SELECT TOP 1 ISNULL(StartDate,'01-01-1900')
FROM TestingTable
ORDER BY StartDate Asc) <> '01-01-1900' THEN 1 ELSE 0 END) AS Testingvalue.
The get the error:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
As koppinjo stated what your current (broken) query is doing is checking if you have a NULL-value (or StartDate = '01-01-1900') in your table, return either a 1 or a 0 depending on which, and then attempting to SUM that single value.
There are 2 different logical things you want.
Either getting the amount of rows that has a StartDate or checking if any row is missing StartDate.
SELECT --Checking if there is a NULL-value in table
(
CASE WHEN
(SELECT TOP 1 ISNULL(StartDate,'01-01-1900')
FROM TestingTable
ORDER BY StartDate Asc) <> '01-01-1900' THEN 1
ELSE 0
END
) AS TestingValue
SELECT SUM(TestingValue) TestingValue --Give the count of how many non-NULLs there is
FROM
(
SELECT
CASE WHEN
ISNULL(StartDate,'01-01-1900') <> '01-01-1900' THEN 1
ELSE 0
END AS TestingValue
FROM TestingTable
) T
Here is a SQL Fiddle showing both outputs side by side.
Hard to say, but you probably want something like this:
SELECT
SUM(TestingValue)
FROM
(SELECT
CASE
WHEN ISNULL(StartDate,'01-01-1900') <> '01-01-1900'
THEN 1
ELSE 0
END AS TestingValue
FROM TestingTable) t
As your original query is written now, your subquery will return 1 value overall, so your sum would be 1 or 0 always, not to mention it is illegal. To get around that, this SQL will apply the case statement to every row in the TestingTable and insert the result into a derived table (t), then the 'outer' select will sum the results. Hope this helps!

SQL Server INLINE IF ELSE

In my table I got a column whose value is whether 0 or 1. If that column is 0 I output the value as 'no'; if 1 I should output as 'yes' for all rows. How can I do this only using SQL statement. Thanks
I understand that this question (which shows up at the top of google results for "sql server inline if") is 2 years old, but with SQL Server 2012, the answers are somewhat outdated. It also appears to be a duplicate of SQL inline if statement type question, but that question (being an even older one), doesn't have an up to date answer either.
In SQL Server 2012 you can use the IIF function:
IIF ( boolean_expression, true_value, false_value )
Example:
SELECT IIF(someColumn = 1, 'yes', 'no')
SQL Server does not have an inline if statement, but it does have an inline case that can be use to accomplish the same.
Case has two forms, one is:
select
case MyFlag
when 1 then 'YES'
when 0 then 'NO'
else 'OOPS'
end
from MyTable
where it's used just like a switch in C-like languages and the other is:
select
case
when MyFlag = 1 then 'YES'
when MyFlag = 0 then 'NO'
-- when some unrelated condition...
else 'OOPS'
end
from MyTable
where it senquentially evaluates a list of conditions and returns the first that is fulfiled.
P.S. The end part is mandatory, and I usually forget that.
It's also usual for a simple case stament to be completely inlined, like
select (case MyFlag when 1 then 'Yes' else 'No' end) as MyFlagDesc
Two possibilities:
(CASE WHEN condition1 THEN Value1 ELSE Value2 END)
or, the most complete solution:
(CASE value_to_check WHEN Value1 THEN Result1 [WHEN ... THEN ...] ELSE OtherResult END)
Something like this:
SELECT
CASE YourColumn
WHEN 0 THEN 'no'
WHEN 1 THEN 'yes'
ELSE 'nothing'
END
FROM dbo.YourTable
I mixed three IIF in one line, I have three variables and I want to know which one is greater than zero but I know the order of priority PersonHomePhoneID , PersonWorkPhoneID and PersonCellPhoneID
IIF(#PersonHomePhoneID > 0 , #PersonHomePhoneID, IIF(#PersonWorkPhoneID > 0 , #PersonWorkPhoneID, IIF(#PersonCellPhoneID > 0 , #PersonCellPhoneID, 0)))
The answer of question :
IIF(column = 1 , 'yes', IIF(column = 0, 'no', ''))

Resources