Функция COUNT () в сочетании с предложением NOT IN не работает должным образом с полем varchar (T-SQL) - PullRequest
7 голосов
/ 25 февраля 2010

Я столкнулся со странной ситуацией, когда пытался подсчитать количество строк, которые НЕ имеют значений varchar, указанных в операторе select. Хорошо, это звучит странно даже для меня, поэтому позвольте мне привести пример:

Допустим, у меня есть поле "MyField" в "SomeTable", и я хочу подсчитать, сколько строк значения MyField не принадлежат домену, определенному значениями "MyOtherField" в "SomeOtherTable". Другими словами, предположим, что у меня есть MyOtherField = {1, 2, 3}, я хочу подсчитать, сколько строк значения MyField не равны 1, 2 или 3. Для этого я бы использовал следующий запрос:

SELECT COUNT(*) FROM SomeTable   
WHERE ([MyField] NOT IN (SELECT MyOtherField FROM SomeOtherTable))   

И это работает как шарм. Однако обратите внимание, что MyField и MyOtherField имеют тип int. Если я попытаюсь выполнить точно такой же запрос, за исключением полей с типом varchar, его возвращаемое значение будет равно 0, хотя я знаю, что есть неправильные значения, я помещаю их туда! И если я, тем не менее, попытаюсь подсчитать обратное (сколько строк ARE в домене противоположно тому, что я хочу, а сколько строк нет), просто подавив предложение «NOT» в запросе выше ... Ну, это работает! ¬¬

Да, для этого должно быть множество обходных путей, но я хотел бы знать, почему это не работает так, как должно. Кроме того, я не могу просто изменить весь запрос, так как большая часть его построена внутри кода C #, и, по сути, единственная часть, которую я могу изменить, это не повлияет ни на одну другую часть программного обеспечения, это оператор выбора, который соответствует домену (все, что указано в предложении NOT IN). Надеюсь, я дал понять, что кто-то может мне помочь.

Заранее спасибо.

Ответы [ 2 ]

6 голосов
/ 25 февраля 2010

Для NOT IN всегда ложно, если подзапрос возвращает значение NULL. Принятый ответ на этот вопрос изящно описывает причину.

Значение NULL для столбца не зависит от используемого типа данных: скорее всего, ваши столбцы varchar имеют значения NULL

Сделай с этим, используй НЕ СУЩЕСТВУЕТ. Для ненулевых значений он работает так же, как NOT IN, поэтому совместим

SELECT COUNT(*) FROM SomeTable S1 
WHERE NOT EXISTS (SELECT * FROm SomeOtherTable S2 WHERE S1.[MyField] = S2.MyOtherField)   
0 голосов
/ 26 февраля 2010

У gbn есть более полный ответ, но я не могу не вспомнить все это. Вместо этого у меня есть религиозная привычка отфильтровывать нули из моих предложений IN:

SELECT COUNT(*)
FROM SomeTable    
WHERE [MyField] NOT IN (
  SELECT MyOtherField FROM SomeOtherTable
  WHERE MyOtherField is not null
)
...