3

I have a need to filter records where:

NotificationRead = 0 || NULL --> IF GetRead = 0
NotificationRead = 1 --> IF GetRead = 1
NotificationRead = 0 || 1 || NULL --> IF GetRead = NULL

Here is the query I am using for this:

DECLARE @GetRead BIT
DECLARE @Query VARCHAR(20)

SET @GetRead = NULL

IF @GetRead = 0 SET @Query = '0,NULL'
ELSE IF @GetRead = 1 SET @Query = '1'
ELSE SET @Query = '0,1,NULL'

SELECT * FROM vwNotifications  WHERE NotificationRead IN (@Query)

The query above basically fails when I supply NULL in the IN clause. I do know the reason why thanks to this question.

But if I take an approach as suggested in that question's answer (using NotificationRead IN (@Query) OR NotificationRead IS NULL), I get all records where NotificationRead = NULL when I don't need them for example, when @GetRead = 1

Can you please point me to the right direction here?

Community
  • 1
  • 1
Moon
  • 33,439
  • 20
  • 81
  • 132
  • 1
    You can't use `NULL` in `IN` clase because `NULL`s cannot be compared with other values/variables in the context of `SQL Server`. For exmaple, the following statement will return nothing: `SELECT * FROM [dbo].[TEST] WHERE [TestColumn] IN (NULL)` – gotqn Apr 25 '14 at 11:33

4 Answers4

6

No, the problem is that you are providing the values as strings.

1 IN (1, 2) -- true.
1 IN ('1, 2') -- false.

Try this instead:

SELECT *
FROM vwNotifications 
WHERE (@GetRead = 0 AND (NotificationRead = 0 OR NotificationRead IS NULL))
OR    (@GetRead = 1 AND NotificationRead = 1)
OR    (@GetRead IS NULL AND (NotificationRead IN (0, 1) OR 
                             NotificationRead IS NULL))
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
3

Others may have a better way, but I would move your select into each of the 'if' statements, and modify accordingly.

IF @GetRead = 0
    SELECT * FROM vwNotifications WHERE NotificationRead IS NULL or NotificationRead = 0
ELSE IF @GetRead = 1 
    SELECT * FROM vwNotifications WHERE NotificationRead = 1
ELSE
    SELECT * FROM vwNotifications WHERE NotificationRead IS NULL or NotificationRead in 0, 1

Note: Please don't actually use SELECT * in production code. Name your columns.

AllenG
  • 8,112
  • 29
  • 40
0

You can add SET ANSI NULLS OS top of query. When added NULL can usable IN (NULL) clause.

SET ANSI NULLS OFF
SELECT * ......
....
WHERE UserId IN (1, 2, NULL)
Mahmut Bedir
  • 487
  • 1
  • 5
  • 23
0

A couple of options:

DECLARE @T TABLE (ID INT IDENTITY(1,1), Notify INT)
DECLARE @GetRead BIT
SET @GetRead = 0

INSERT INTO @T
        ( Notify )
VALUES  ( 0  -- Notify - int
          )

INSERT INTO @T
        ( Notify )
VALUES  ( 1  -- Notify - int
          )

INSERT INTO @T
        ( Notify )
VALUES  ( NULL  -- Notify - int
          )

SELECT *
FROM @t t
WHERE @GetRead IS NULL 
    OR (@GetRead = 0 AND (t.Notify =0 OR t.Notify IS NULL))
    OR (@getRead = 1 AND t.Notify = @GetRead)

SELECT *
FROM @t t
WHERE @GetRead IS NULL 
    OR ISNULL(t.notify, 0) = @GetRead
Stuart Ainsworth
  • 12,792
  • 41
  • 46