SELECT WHERE {column} = CASE WHEN {expression} THEN NULL - sql

I have this code which is part of a stored procedure
INSERT INTO #TempTable
/* A few subqueries, about 100 lines */
WHERE (cartera.ClaSucursal = #pIdSucursal OR #pIdSucursal = -1)
AND (cartera.ClaAsesorActual =
CASE
WHEN #pIdAsesor > 0 THEN #pIdAsesor
WHEN #pIdAsesor = 0 THEN NULL
END
OR #pIdAsesor = -1)
/* Rest of my code, about 200 lines */
SELECT * FROM #TempTable
Basically I have a parameter called #pIdAsesor and depending on its value there can be three possible outcomes.
#pIdAsesor = -1 which brings me all entries regardless of the Id value
#pIdAsesor = sumId which brings me all entries with given Id
#pIdAsesor = 0 which brings me all entries with NULL as the Id
Outcomes 1 and 2 work flawlessly, but scenario 3 doesn't bring back results.

null isn't a value - it's the lack thereof. null is never equal to anything (not even another null), but you can check for it explicitly with the is operator.
You could ditch the case expression and construct this logic with a series of ors:
AND ((#pIdAsesor = -1) OR
(#PIdAsesor = 0 AND cartera.ClaAsesorActual IS NULL) OR
(#pIdAsesor = cartera.ClaAsesorActual))

You can't use = for null in case when result comes null but = null doesn't work. You have to use is null.

Related

Using SELECT subquery in a CASE statement and handling NULLS

I have 2 SQL tables one holding stock information then a style table which details how the stock is used. For some jobs the information is contained with a print file so the value in the stock table would be BIN, if not it would contain a template name which would cause a query to a Styles table which then shows how the stock is used. There a 10 positions that a stock could be applied but the template table wouldn't have records for where a stock couldn't be used (on the back of a simplex job for example).
I have a stored procedure which works to provide the detail based on whether the logic value is BIN or not but for the records in the style table that have no value I get NULL back which I need to suppress but just putting ISNULL around the column name in the subquery isn't having any effect. Am I just missing something as I'd rather not nest in another CASE statement to check if the query would produce NULL
WITH STYLES AS
(
SELECT
#JOBNAME AS JobName, Logic AS StyleName
FROM
[dbo].[CON_Tbl_511_DigitalStocks]
WHERE
JOBNAME = #JOBNAME
)
SELECT TOP 1
[Logic],
[S1F], [S1B], [S2F], [S2B],
[S3F], [S3B], [S4F], [S4B],
[S5F], [S5B],
CASE
WHEN b.stylename = 'BIN'
THEN --checks if there is a style for this job
CASE
WHEN S1F = '' THEN ''
ELSE '1'
END -- if a stock code is specified then return the bin name ("1")
ELSE (SELECT PAGE
FROM [dbo].[CON_Tbl_512_DigitalLogic]
WHERE STYLENAME = B.StyleName
AND STOCKREF = 'S1F')
END AS S1F_LOGIC, -- If a style is used return the style instruction for this bin and side
CASE
WHEN b.stylename = 'BIN' -- repeat this for all bins/sides
THEN
CASE WHEN S1B = '' THEN ''
ELSE '1'
END
ELSE (SELECT PAGE
FROM [dbo].[CON_Tbl_512_DigitalLogic]
WHERE STYLENAME = B.StyleName AND STOCKREF = 'S1B')
END AS S1B_LOGIC,
CASE WHEN b.stylename = 'BIN' THEN
CASE WHEN S2F = '' THEN ''
ELSE '2' END
ELSE (SELECT PAGE FROM [dbo].[CON_Tbl_512_DigitalLogic] WHERE STYLENAME = B.StyleName AND STOCKREF = 'S2F') END AS S2F_LOGIC -- this one returns NULL as there is no instruction required for "2SF"
FROM
[CON_Tbl_511_DigitalStocks] A
JOIN
STYLES B ON A.JOBNAME = B.JOBNAME
WHERE
A.JobName = #JobName
This code works fine until the last one as there is no value in the stockref column that says 'S2F' but putting SELECT ISNULL(PAGE, '') still returns NULL
Because this query is not finding any records:
SELECT PAGE FROM [dbo].[CON_Tbl_512_DigitalLogic] WHERE STYLENAME = B.StyleName AND STOCKREF = 'S2F'
and you want it to return something, you can change it to:
SELECT coalesce(min(PAGE),'') FROM [dbo].[CON_Tbl_512_DigitalLogic] WHERE STYLENAME = B.StyleName AND STOCKREF = 'S2F'
This will return the minimum value (min) of the found records, which will return NULL when noting found. The coalesce will turn this NULL into the empty string: ''
P.S.: see also SQL - Difference between COALESCE and ISNULL?

Update multiple values using IS NULL condition

I just finished migrating an Access database to the SQL Server and I need to fix the Yes/No values to be defaulted to No as their data type conversion is set to bit.
I do this by setting the default value to 0.
However, I want to execute a query to do that as well, but there are multiple bit rows.
I know how to use multiples with the SET command, but how do we use multiple with WHERE? What is the proper way of structuring it?
UPDATE sometable SET
[isConditionOnePassed] = 0
, [isSecondPassed] = 0
, [isThirdPassed] = 0
WHERE [isConditionOnePassed] IS NULL, [isSecondPassed] is NULL, [isThirdPassed] IS NULL
Or is it with an AND? Like boolean logic?
UPDATE sometable SET
[isConditionOnePassed] = 0
, [isSecondPassed] = 0
, [isThirdPassed] = 0
WHERE [isConditionOnePassed] IS NULL and [isSecondPassed] is NULL and [isThirdPassed] IS NULL
Hmmm . . . If you want to set NULL values to another value, you can use COALESCE():
UPDATE sometable
SET isConditionOnePassed = COALESCE(isConditionOnePassed, 0),
isSecondPassed = COALESCE(isSecondPassed, 0),
isThirdPassed = COALESDCE(isThirdPassed, 0)
WHERE isConditionOnePassed IS NULL OR isSecondPassed is NULL OR isThirdPassed IS NULL;
Seems like what you really need is an ISNULL or CASE expression. Here is an example with both:
UPDATE dbo.SomeTable
SET isConditionOnePassed = ISNULL(isConditionOnePassed,0),
isSecondPassed = CASE isSecondPassed WHEN 1 THEN 1 ELSE 0 END;

SQL : Update value when the value in the database is null

I know this is already asked question and possible to be close.
But i really want a answer, I already searched through the internet, Read documentations, Blogs, and Question to SO.
This is my Query so Far,
declare #count numeric
select #count = (select count(1) from E496_TitleReference a where
exists (select 1 from #tempTransactions b where a.EPEB_RoD = b.tEPEB_RoD and
a.EPEB_ENO = b.tEPEB_ENO and a.EPEB_ID = b.tEPEB_ID and a.Title_Seq = b.tTitle_Seq))
update E496_TitleReference
set PrintStatus = '{0}',Is_AESM=isnull(-1,Is_AESM)
from E496_TitleReference a where
exists (select 1 from #tempTransactions b where a.EPEB_RoD = b.tEPEB_RoD and
a.EPEB_ENO = b.tEPEB_ENO and a.EPEB_ID = b.tEPEB_ID and a.Title_Seq = b.tTitle_Seq)
if ##rowcount <> #count
begin
rollback tran
Print "Error: There is an error on table E496_TitleReference."
return
end
go
For eg, In my table in Database i have column name Is_AESM, In Is_AESM column it have 4 values.
Is_AESM
NULL
NULL
-1
-2
Something like this.
Now when i run my script, it has no problem when i run it,
Is_AESM=isnull(-1,Is_AESM)
In this query it will detect if Is_AESM is null, it will update Is_AESM = -1 if not it will retain the value.
Now my problem is, if my query detect Is_AESM has a null value, it will update all the value to -1.
Is_AESM
-1
-1
-1
-1
The result is something like that. Now i want is update only the null value not all the value in column Is_AESM.
I think this query is wrong Is_AESM=isnull(-1,Is_AESM).
Any ideas will be a big help.
You may try with coalsece() function
update E496_TitleReference
set PrintStatus = '{0}',Is_AESM=coalsece(Is_AESM,-1)
from E496_TitleReference a where
exists (select 1 from #tempTransactions b where a.EPEB_RoD = b.tEPEB_RoD and
a.EPEB_ENO = b.tEPEB_ENO and a.EPEB_ID = b.tEPEB_ID and a.Title_Seq = b.tTitle_Seq)
you need to replace order of parameters.
Is_AESM=isnull(Is_AESM, -1)
You can use COALSECE function. It returns the first non-null entry from the given list. So:
Is_AESM= COALSECE(IS_AESM,-1)
This will return IS_AESM value if it is not null (since it is the first non-null value)
Else if IS_AESM is NULL then it returns -1 (since it is the non-null value)

CASE Statement in WHERE statement (equal to and not equal to)

I have the following query where I'm trying to return different values from a table based off the values of a bit variable.
Is there a way I can substitute the where condition to get that to work?
DECLARE #isAggregate bit = 0
SELECT
*
FROM
Fields
WHERE
FieldType
CASE
WHEN #isAggregate = 1 THEN = 'Aggregate'
WHEN #isAggregate = 0 THEN <> 'Aggregate'
END
You can use boolean logic, case expression will not work in this way :
where (#isAggregate = 1 and FieldType = 'Aggregate') or
(#isAggregate = 0 and FieldType <> 'Aggregate')

CASE Statement in where clause using equal to and IN

WHERE CONDITION1='ABC'
AND Status =
CASE #Option
WHEN 1 THEN 'True'
WHEN 2 THEN 'False'
WHEN 3 THEN NULL
WHEn 4 THEN **IN ('True', 'False', NULL)**
END
How do I write a query where my first options match directly using = but my last option needs an IN
The above query gives error, but I want something similar to it, which I am not able to find out.
A CASE statement can't return a set of values... but this query should give you the same results:
WHERE CONDITION1='ABC'
AND Status =
CASE
WHEN 1 THEN 'True'
WHEN 2 THEN 'False'
WHEN 3 THEN NULL
WHEN 4 THEN Status
END
Also, note that unless you have ANSI_NULLS OFF, Status will never = NULL... you would need to use IS NULL for this comparison, and you'd need to forgo the CASE statement altogether.
Skip the CASE statement and use OR. And as per ANSI standard don't compare with NULL:
WHERE CONDITION1='ABC'
AND ((#Option = 1 AND Status = 'True') OR
(#Option = 2 AND Status = 'False') OR
(#Option = 3 AND Status IS NULL) OR
(#Option = 4 AND (Status IS NULL OR Status IN ('True', 'False'))))