WHERE field1 IN (NULL)

2020-04-21 06:56发布

问题:

I want to retrieve data from the table based on a couple of columns, some with data, other with NULL. In the first code example below, the procedure is fine - all the rows are returned. In the second example no rows are returned - because NULL=NULL return FALSE.

The third example is more or less what I have in mind, when the column has NULL values, then this clause has to be "ignored" and only the data in the first two columns are used to return the rows based on these two columns.

SELECT * FROM XYZ
WHERE col1 IN ('a', 'b')
AND col2 IN ('c', 'd')
AND col3 IN ('e', 'f')


SELECT * FROM XYZ
WHERE col1 IN ('a', 'b')
AND col2 IN ('c', 'd')
AND col3 IN (NULL) --???


SELECT * FROM XYZ
WHERE col1 IN ('a', 'b')
AND col2 IN ('c', 'd')
--AND col3 IN (NULL) --IGNORED

Currently I use a dynamic SQL statement, but is very slow.

SET @EventCodeList = 
(SELECT REPLACE(tEventCode, ' ', '') FROM tblActivityPerCC_Config WHERE tCostCenter = @CostCenter) 


SET @EventCodeStr = 
CASE WHEN @EventCodeList IS NULL THEN ' logs.tEventCode LIKE (''%'') '
ELSE ' logs.tEventCode IN (SELECT qValue FROM nsEMV.dbo.fncReturnCommaDelimitedStringAsTable(@EventCodeList))'
END

SET @SQLString = N'  
SELECT
    ccg.Field1,
    logs.Field2     
FROM dbo.tblEMV_Logsheet AS logs 
INNER JOIN dbo.tblLookup_EMVEquipment AS ccg ON logs.tEquipmentKey = ccg.tEquipmentKey
WHERE tDate BETWEEN ''' + CONVERT(varchar(30), @BMonth) + ''' AND ''' + CONVERT(varchar(30), @EMonth) + ''' 
AND  logs.tAreaCode IN ('XYZ', 'ABC') 
AND ' + @EventCodeStr + ' --THE FOLLOWING COLUMNS MAY HAVE NULL VALUES
AND ' + @SourceStr + '
AND ' + @DestinationStr'

Any help would be appreciated.

IN RESPONSE TO Jayvee's SUGGESTION BELOW: This does not do what was intended or I do something wrong!

CREATE TABLE #temp
(
value varchar(10),
value2 varchar(10)
)

INSERT INTO #temp (value, value2) SELECT '5', '3'
INSERT INTO #temp (value, value2) SELECT NULL, '2'
INSERT INTO #temp (value, value2) SELECT '4', NULL
INSERT INTO #temp (value, value2) SELECT '6', '2'
INSERT INTO #temp (value, value2) SELECT '6', NULL
INSERT INTO #temp (value, value2) SELECT '6', '4'
INSERT INTO #temp (value, value2) SELECT NULL, '1'
INSERT INTO #temp (value, value2) SELECT NULL, '4'

SELECT value as [value],value2 as [value2]  FROM #temp
WHERE ISNULL(value,'') IN ('4')
AND ISNULL(value2,'') IN ('4')

DROP TABLE #temp

回答1:

Try IS NULL

SELECT * FROM XYZ 
WHERE col1 IN ('a', 'b') 
AND col2 IN ('c', 'd') 
AND col3 IS NULL   -- Instead of IN (NULL)


回答2:

for each column test it against your parameter and include the IS NULL test, combine these with parentheses, like this:

SELECT
      *
FROM XYZ
WHERE (col1 IN ('a', 'b') OR col1 IS NULL)
  AND (col2 IN ('c', 'd') OR col2 IS NULL) 
  AND (col3 IN (NULL) OR col3 IS NULL)

here col3 IN (NULL) is used to demonstrate a parameter that was not provided



回答3:

something like this should work:

SELECT * FROM XYZ
WHERE ISNULL(col1,'') IN ('a', 'b','')
AND   ISNULL(col2,'') IN ('c', 'd','')
AND   ISNULL(col3,'') IN ('')