2014-12-30 2 views
2

Это должна быть простая ошибка с моей стороны. У меня есть таблица с разрешениями (у заявителей есть одно разрешение) - около 600 лет истек в прошлом сезоне и ~ 900 в прошлом сезоне. Мне нужно создать список рассылки уникальных претендентов, у которых были разрешения в течение последних двух сезонов.SQL Не возвращается Ожидаемые отчеты

SELECT COUNT(*) FROM Backyard_Burn WHERE YEAR(Expiration_Date)= 2014 

SELECT COUNT(*) FROM Backyard_Burn WHERE YEAR(Expiration_Date)= 2013 

SELECT COUNT(*) FROM Backyard_Burn WHERE YEAR(Expiration_Date)= 2013 
AND Applicant_Mail_ID NOT IN(
    SELECT Applicant_Mail_ID 
    FROM Backyard_Burn 
    WHERE YEAR(Expiration_Date)= 2014) 

Который возвращает: 618, 923 и 0

Почему 0 и не число где-то около 923 - 618 предполагающей большинство из них повторяют кандидаты?

ответ

4

NOT IN может быть опасным. Проблема, вероятно, вызвана тем, что Applicant_Mail_id принимает значения NULL. Вы можете исправить это легко с:

SELECT COUNT(*) 
FROM Backyard_Burn 
WHERE YEAR(Expiration_Date) = 2013 AND 
     Applicant_Mail_ID NOT IN (SELECT Applicant_Mail_ID 
           FROM Backyard_Burn 
           WHERE YEAR(Expiration_Date) = 2014 AND Applicant_Mail_ID IS NOT NULL 
           ); 

Если какой-либо из этих значений являются NULL, то NOT IN может возвращать только FALSE или NULL - условие не может позволяет записи через.

По этой причине, я думаю, что лучше использовать NOT EXSTS, которая имеет семантику вы ожидаете, когда некоторые значения могут быть NULL:

SELECT COUNT(*) 
FROM Backyard_Burn bb 
WHERE YEAR(Expiration_Date) = 2013 AND 
     NOT EXISTS (SELECT 1 
        FROM Backyard_Burn bb2 
        WHERE YEAR(bb2.Expiration_Date) = 2014 AND 
         bb2.Applicant_Mail_ID = bb.Applicant_Mail_ID 
       ); 

EDIT:

По дороге, альтернативный способ формулирования этого является использование group by и having:

select Applicant_Mail_ID 
from Backyard_Burn 
group by Applicant_Mail_ID 
having sum(case when year(Expiration_Date) = 2013 then 1 else 0 end) > 0 and 
     sum(case when year(Expiration_Date) = 2014 then 1 else 0 end) > 0; 

Это позволяет избежать проблемы Wi го NULL с и позволяет легко добавлять новые условия, такие как заявители, которые сделали не есть какая-либо запись в 2012.

+0

Я добавил И Applicant_Mail_ID НЕ ЯВЛЯЕТСЯ ВЫБОРОМ, и правильное количество записей возвращается. благодаря! – rheitzman

0
  1. вам нужны заявители из последних двух сезонов - вам нужно использовать больше, чем оператор
  2. лучше, чтобы проверить на полную дату вместо того, чтобы значение года с year
  3. , чтобы получить уникальные заявителей вы можете использовать distinct

Какие результаты в:

select count(distinct Applicant_Mail_ID) 
from Backyard_Burn 
where Expiration_Date >= '20130101'; 
Смежные вопросы