How do I incorporate "where [binary] is not null" in a T-SQL select statement? - sql

I have a stored procedure that I need to filter rows that have a binary value and return only rows that are not null in the binary column.
When I execute this stored procedure:
create procedure sp_GetGraduatingStudentDataByYear
(
#year nvarchar(4)
)
as
select * from Cohort_Graduation_Student_Data where Exp_Grad_Year = #year and Off_Track != null
go
I get no results.
How can I alter this script to return the rows with a null value in the binary column?

This is not because it's a binary column, but because null in SQL should not be compared to anything. Essentially, Off_Track != null condition filters out all rows - all checks for column = null and column != null always evaluate to false.
Use is not null instead:
select *
from Cohort_Graduation_Student_Data
where Exp_Grad_Year = #year and Off_Track is not null

Related

SQL Server WHERE clause : column IS NULL or column = parameter value

The code snippet below is what I'm trying to achieve, but I'm having trouble making it work. If the parameter that gets passed into the procedure is null, I want to only return the rows with a WHERE clause IS NULL, but if there is a value, I want to return the rows that are equal to the value passed in. Dynamic SQL seems like it would work, but I'm curious if there's an easier way I'm missing. Thanks in advance.
PARAM:
#id varchar(10) = '123456789'
SELECT *
FROM TABLE T
WHERE
CASE
WHEN #id IS NULL THEN (id IS NULL)
ELSE id = #id
END
The logic you want is:
WHERE (#id IS NULL AND id IS NULL) OR
id = #id
You're trying to use a CASE expression like a Case (Switch) statement. Switches don't exist in T-SQL, and a CASE expression returns a scalar value not a boolean result.
Don't, however, use CASE expressions in the WHERE, use proper Boolean logic:
SELECT *
FROM YourTable YT
WHERE (ID = #ID
OR (ID IS NULL AND #ID IS NULL))

How to set NULL in a Coalesce

Quick question on Coalesce:
clw.ClawbackPercent = Coalesce(#ClawbackPercent, clw.ClawbackPercent)
Lets say for column 'ClawbackPercent' I have a value of 100.
If I execute a proc and set parameter #ClawbackPercent to have the value NULL, it keeps the value 100 in the row for that column which is great.
However, if I want to set 100 to actually be NULL, what do I need to write in the exec proc statement or what do I need to add in the Coalesce statement?
Thank you
It sounds like you want 100 to be the Default value of a stored proc parameter, not necessarily to replace all NULLs with this value. If this is the case, you don't want a COALESCE but you do need to provide a default value for the parameter on the proc definition.
e.g.
CREATE PROC dbo.MyProc (
#MyParam INT = 100
)
AS
-- My code here
If somebody executes this proc without specifying a value for #MyParam, the default of 100 will be assigned. If they explicitly specify #MyParam = NULL then NULL will be assigned..
Then probably you should not use coalesce, instead you can use case statement as below:
clw.ClawbackPercent = CASE WHEN #ClawbackPercent = 100
THEN NULL
ELSE
#ClawbackPercent END
in the select statement
You have to write in the following way:
CREATE PROCEDURE sp_test(
#ClawbackPercent VARCHAR(30)
) AS
BEGIN
SELECT COALESCE(#ClawbackPercent, '100')
END
--call as below and if you want to return second value then, EXEC sp_test NULL
--if your second, thirds... parameters are in INTEGER then simply CAST to VARCHAR
EXEC sp_test 'NULL'

Bit parameter with Null value in Stored Procedure

I'm having a bit value in my table, which contains bit (0 or 1) and NULL (as default).
Here is my SProc:
CREATE PROCEDURE msp_CustomerStatistics
#Postal_MinValue int,
#Postal_MaxValue int,
#SubscriberState bit,
#CustomerType varchar(50)
BEGIN
[...]
WHERE Sub = #SubscriberState
AND Postal BETWEEN #Postal_MinValue AND #Postal_MaxValue
AND CustType = #CustomerType
END
When I pass the #SubscriberState parameter with 1 or 0, the result is correct.
But when I pass null, the result is 0, which ain't correct.
If I create a SQL select with following where clause:
WHERE Sub IS NULL
Then the result shows the correct count.
Any idea how I make my Stored Procedure working with NULL parameter in my WHERE clause too??
You can not use the = operator with null values. Comparisons with NULL always return false. Try to modify your WHERE statement to the following:
WHERE (Sub = #SubscriberState OR (#SubscriberState IS NULL AND Sub IS NULL))
You could either set null values to 0 and check it like this:
WHERE Isnull(Sub,0) = #SubscriberState
or have a tri-state sort of bodge like:
WHERE Isnull(Sub,3) = isnull(#SubscriberState,3)

How to write filtered queries using SQL stored procedures?

How can I write a SQL stored procedure where I want the parameters to be optional in the select statement?
try this.. Make the SPs input parameters that control the filtering optional, witrh default values of null. In each select statement's Where clause, write the predicate like this:
Create procedure MyProcedure
#columnNameValue [datatype] = null
As
Select [stuff....]
From table
Where ColumnName = Coalesce(#columnNameValue , ColumnName)
this way if you do not include the parameter, or if you pass a null value for the parameter, the select statement will filter on where the column value is equal to itself, (effectively doing no filtering at all on that column.)
The only negative to this is that it prevents you from being able to pass a null as a meaningfull value to explicitly filter on only the nulls.... (i.e., Select only the rows where the value is null) Once the above technique has been adopted, you would need to add another parameter to implement that type of requirement. ( say, #GetOnlyNulls TinyInt = 0, or something similar)
Create procedure MyProcedure
#columnNameValue [datatype] = null,
#GetOnlyNulls Tinyint = 0
As
Select [stuff....]
From table
Where (ColumnName Is Null And #GetOnlyNulls = 1)
Or ColumnName = Coalesce(#columnNameValue , ColumnName)

Returning integer value that represents the first non-null field

I've created the following stored procedure:
ALTER PROCEDURE [dbo].[ExampleSP]
(
#SearchText NVARCHAR(4000),
#ID INT = NULL
)
AS
BEGIN
SET NOCOUNT ON;
SELECT
deID,
deTitle
FROM tblDemo As de
LEFT JOIN tblLinkTable As lnk ON (lnk.ID = de.deID)
WHERE CONTAINS(cstKeywords, #SearchText)
AND ((#ID IS NULL) OR (lnk.ID = #ID))
GROUP BY deID,Title
ORDER BY de.Title
But I also need to be able to find the first field that is not null out of the following table columns:
deIntroText, deCompanyText, deTimetableText and deExampleText
And i need to do this for each record that is returned from the SELECT.
So I realise that i'd need to create a temporary column to store it in and i guess you'd need to use an IF statement like this:
IF deIntroText IS NOT Null
THEN TempFieldToReturn = 1
ELSE IF deCompanyText IS NOT Null
THEN TempFieldToReturn = 2
ELSE IF deTimetableText IS NOT Null
THEN TempFieldToReturn = 3
ELSE IF deExampleText IS NOT Null
THEN TempFieldToReturn = 4
So my question is - what is the best way to achieve this? Any examples would be appreciated.
No real shortcut - just use a CASE expression:
SELECT
/* Other Columns */
CASE
WHEN deIntroText IS NOT Null THEN 1
WHEN deCompanyText IS NOT Null THEN 2
WHEN deTimetableText IS NOT Null THEN 3
WHEN deExampleText IS NOT Null THEN 4
ELSE 5 END as OtherColumn
FROM
/* Rest of query */
This is a Searched CASE - there are actually two variants of CASE. I guessed at 5 if all of the columns are NULL - you might leave off the ELSE 5 portion, if you want a NULL result in such a case.