coalesce and a case statement - explanation? - sql

I'm working on a query that doesn't seem to be doing what it's supposed to since being transferred from one SSRS server to another, and the following line in part of the where statement appears to be where the difference is, or at least from what I can find.
where COALESCE(field, -1) = CASE field WHEN 1 THEN 0 ELSE -1 END
I know it's probably a bit generic but can anyone shed any light on what this may be doing? I've read up on coalesce and gather that it finds the first non-null value from the specified list of fields, but I don't understand what the '-1' does there.
I hope it's not too general a question and that someone can give me a clue as to what it may be doing

Without context it's difficult to give a truly helpful answer.
At first glance it looks as though it could be rewritten much more simply from this:
WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
to this:
WHERE COALESCE(#field, -1) = -1
If that is true then basically you are saying that if the field is null or the field equals -1 then the condition is true otherwise it's false.
Here are some tests to try to prove this:
-- Original
DECLARE #field INT
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = -1
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = 0
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = 1
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = 2
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = 3
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
--Rewritten
DECLARE #field INT
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = -1
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = 0
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = 1
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = 2
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = 3
SELECT 1 WHERE COALESCE(#field, -1) = -1
Both sets of queries in this test give the same results, but as I said without context and realistic test data it's difficult to know if there was a reason why the query was written in the way that it originally was.
Here is another example from a different perspective, using a LEFT JOIN:
DECLARE #MainTable AS TABLE(ident INT)
DECLARE #PossibleNullTable AS TABLE(mainIdent INT, field INT)
INSERT INTO #MainTable(ident) VALUES(1)
INSERT INTO #MainTable(ident) VALUES(2)
INSERT INTO #MainTable(ident) VALUES(3)
INSERT INTO #MainTable(ident) VALUES(4)
INSERT INTO #MainTable(ident) VALUES(5)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(1,-1)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(1,1)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(1,0)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(2,0)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(3,1)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(5,-1)
--Original
SELECT *
FROM #MainTable mt
LEFT JOIN #PossibleNullTable pnt
ON mt.ident = pnt.mainIdent
WHERE COALESCE(field, -1) = CASE field WHEN 1 THEN 0 ELSE -1 END
--Original Result
ident mainIdent field
1 1 -1
4 NULL NULL
5 5 -1
--Rewritten
SELECT *
FROM #MainTable mt
LEFT JOIN #PossibleNullTable pnt
ON mt.ident = pnt.mainIdent
WHERE COALESCE(field, -1) = -1
--Rewritten Result
ident mainIdent field
1 1 -1
4 NULL NULL
5 5 -1
Again both queries in this test give the same results.

the first non-null value from the specified list of fields
This means the list of fields between the parenthesis. For instance:
COALESCE(col1,col2,col3,-1)
means that if col1 is not null then use this, else check col2. If col2 is null then check col3. If that is null too then use -1 as the value.
In your example, COALESCE(field, -1) is equivalent to ISNULL(field, -1)
In my example COALESCE(col1,col2,col3,-1) is equivalent to ISNULL(ISNULL(ISNULL(col1, col2), col3), -1)

This is a bit complex expression used in where clause, that suggests
use field column, replace NULL values with -1 & compare all these values of field column with the case expression such as,
here at first, we have to consider that there is no null value in field column as we have replaced all null with -1 using coalesce().
then in case statement, if the values is 1 then it is replace by 0. So 0 is checked with coalesce(field,-1), if it is also 0, then expression is true else false.
Similar for field value -1 using case.

Related

A SQL query to count how many attributes a record has in common with another record?

I am trying to write a SQL query to take the count of columns with equal value in my schema for each row by comparison to a single record.
Example:
record1: 1, 0, 1, 0, 0
record2: 0, 0, 0, 0, 1
record3: 0, 0, 1, 0, 0
record1 has 2 attributes in common with record2, go through the entire table and order by number of attributes each record has in common with record1
Is there a way to write a SQL statement that will do this? I have only found ways to compare each row and specify which attributes must be of equal value.
You can do:
select t.*,
((case when t.col1 = t1.col1 then 1 else 0 end) +
(case when t.col2 = t1.col2 then 1 else 0 end) +
(case when t.col3 = t1.col3 then 1 else 0 end) +
. . .
) as num_in_common
from t cross join
t t1
where t1.id = 1; -- or however you define "record1"
order by num_in_common desc;
Here's a nice routine you can use in SQL Server that will do this if you'd like. Replace #temp with your table name:
declare #holding table (id int, col1 int, col2 int, col3 int, col4 int, col5 int, num_in_common int)
declare #iterator int = 1
declare #row1col1 int, #row1col2 int, #row1col3 int, #row1col4 int ,#row1col5 int
while #iterator<=(select max(id) from #temp)
begin
if #iterator=1
select #row1col1=col1, #row1col2=col2, #row1col3=col3, #row1col4=col4 ,#row1col5=col5
from #temp where id=#iterator
else
insert #holding
select *, case when col1-#row1col1 = 0 then 1 else 0 end +
case when col2-#row1col2 = 0 then 1 else 0 end +
case when col3-#row1col3 = 0 then 1 else 0 end +
case when col4-#row1col4 = 0 then 1 else 0 end +
case when col5-#row1col5 = 0 then 1 else 0 end
from #temp where id=#iterator
set #iterator=#iterator+1
end
select * from #holding

Update Zero to One and One to Zero in SQL Server

I have a table with flag 0 and 1.
Please tell me how to update Zero to One and One to Zero
DECLARE #a INT, #b INT
SELECT #a = number
FROM zerone
WHERE number = 0
SELECT #b = number
FROM zerone
WHERE number = 1
BEGIN
IF #a = 0
UPDATE zerone
SET number = 1
WHERE #a = 0
ELSE IF #b = 1
UPDATE zerone
SET number = 0
WHERE #b = 1
END
This query is not working for me.
use the below query to update 0 to 1 and 1 to 0
update zerone set number= 1-number
Just this:
UPDATE zerone
SET number = CASE WHEN number = 1 THEN 0 ELSE 1 END;
you should also always consider NULL values in update operations and must explicitly filter them out
UPDATE zerone
SET number= case
when 1 then 0
when 0 then 1
end
WHERE number in (0,1)
Also your query will not work because you are assigning a single variable with a rows of data in the select statement.
SELECT #a = number
FROM zerone
WHERE number = 0
This does not work like as you are expecting and will only assign #a with value either NULL(if there are no rows) or with 0 if there is a row. If there are multiple rows even then it will have a single value 0
As you have seen there are so many ways to perform that task but in this case, I would prefer #Abdul Rasheed.
We can also use below IIF logical function in SQLSERVER2012 or above.
UPDATE zerone
SET number = IIF (number = 1, 0, 1)

Range of values as ELSE clause in a CASE statement

I have a stored proc which is supposed to filter results based on an integer which can be NULL and I need to be able to choose results that either match the integer or retrieve all results but I can't figure out the syntax for the "All" results part. Query is basically this:
Select * from dbo.TABLE
WHERE [IDField] =
CASE
WHEN ISNULL(#ID, 0) > 0 THEN #ID
ELSE ?????
END
I want to use an IN range to include all the values because setting it to 0 or Null will return no results, but this doesn't work:
Select * from dbo.TABLE
WHERE [IDField] =
CASE
WHEN ISNULL(#ID, 0) > 0 THEN #ID
ELSE 1 OR 2 OR 3
END
or this:
Select * from dbo.TABLE
WHERE [IDField] IN (
CASE
WHEN ISNULL(#mID, 0) > 0 THEN #mID
ELSE 1,2,3
END
)
Phrase this without the case:
SELECT *
FROM dbo.TABLE
WHERE #id is null OR IDField = #id;
Then you can expand this to:
SELECT *
FROM dbo.TABLE
WHERE (COALESCE(#ID, 0) > 0 AND IDField = #id) OR
IDField IN (1, 2, 3)

Choose multiple cases condition

I want to get multipule choises after then in case statment as
#value
select * from [dbo].[Currency_Tbl]
WHERE [Currency_Active_YN]=
CASE WHEN #value = 1 THEN
( 1 or 0)
ELSE
#Value = 0 then 0
END
it didn't accept the first line in col1 but accept the col2
how can I select multiple numbers after THEN?
You don't use case in where clauses. Use boolean logic
select * from [dbo].[Currency_Tbl]
WHERE (#value = 1 and [Currency_Active_YN] in (0,1))
OR (#value = 0 and [Currency_Active_YN] = 0)
You dont need a case to do what you're trying to do. Assuming Currency_Active_YN is a not null bit field the following logic should suffice.
select * from [dbo].[Currency_Tbl]
WHERE (#value=1 OR [Currency_Active_YN]=#Value)

Help deciphering Stored Procedure

I can't for the life of me figure out how this stored procedure works or what it is doing exactly, I know it works as is but I'm trying to limit some database calls which requires modifying this stored procedure.
CREATE PROCEDURE scriptassist.getQueue
#Status smallint = -1,
#GroupID uniqueidentifier = null,
#MACAddress varchar(200) = ''
AS
SET NOCOUNT ON
Print #GroupID
SELECT *
FROM [Queue]
WHERE
case #Status
When -1 Then
Case When ISNULL(Status,0) <> 1 Then 1 Else 0 End
Else
Case When ISNULL(Status,0) = #Status Then 1 Else 0 End
End =1
And
case When #GroupID IS NULL Then 1
Else
Case When GroupID = #GroupID Then 1 Else 0 End
End =1
And
case #MACAddress
When ''
Then 1
Else
Case When MACAddress = #MACAddress Then 1 Else 0 End
End =1
Order By DateEntered DESC
I know that somehow it is dynamically defining the Where Clause but I'm not sure what is getting done. Also if anyone knows of a tool that would let me see what is actually happening, thanks!
You're right in noticing that it's dynamically filtering the WHERE clause. Take for example
case #MACAddress
When ''
Then 1
Else
Case When MACAddress = #MACAddress Then 1 Else 0 End
End =1
If the MACAddress is the empty string then it is not used to filter the results. (The Case statement returs 1, which is then compared with 1 at the end, resulting in TRUE, so the row is included.)
If the #MACAddress parameter is not the empty string, then it's compared with the MACAddress column in the table. If there is a match 1, is returned, which is equal to 1, and so the row is included. If there is no match, 0 is returned, which does not equal 1 and the row is excluded.
Selects values from Queue based on three criteria that could be passed. If the passed variable #Status=-1, or #GroupID is null, or #MACAddress ='', they are not used in the Where criteria. If they are present, then they are used in the Where criteria.
When each case statement returns 1, the corresponding record in the Queue table is returned.