2016-11-09 3 views
0

Я пытаюсь отфильтровать результаты, которые были добавлены конкретным пользователем, сохраняя каждый день, поскольку этот запрос будет использоваться для диаграммы в отчете. Когда я удаляю t2.createdBy <> 21, я получаю все даты, но мне также нужны результаты для фильтрации, чтобы это было правильно.T-SQL: как сохранить левое соединение, но запрос фильтра

Запрос:

SELECT 
    t1.DateFull, COUNT(t2.ContainerWashedDate) as Washes 
FROM 
    DateLookup t1 
LEFT JOIN 
    factContainerWash t2 ON t1.Datefull = t2.ContainerWashedDate 
WHERE 
    (t1.DateFull >= '10/5/2016') 
    AND (t1.DateFull <= '11/9/2016') 
    AND t2.createdBy <> 21 
GROUP BY 
    t1.DateFull 
ORDER BY 
    DateFull 

Результаты:

DateFull     | Washes 
-------------------------+------- 
2016-10-05 00:00:00.000 | 1231 
2016-10-06 00:00:00.000 | 466 
2016-10-10 00:00:00.000 | 84 
2016-10-12 00:00:00.000 | 75 

Ожидаемые результаты:

DateFull     | Washes 
-------------------------+------- 
2016-10-05 00:00:00.000 | 1231 
2016-10-06 00:00:00.000 | 466 
2016-10-07 00:00:00.000 | 655 
2016-10-08 00:00:00.000 | 23 
+0

Но 'createdBy' ** не может ** быть 21, если его вообще нет. У вас есть логическая проблема, с которой вам нужно справиться в первую очередь. – Amit

ответ

2

Ниже приведены три подхода. Когда я начал отвечать на этот вопрос, я понял, что могут произойти разные вещи. Вероятно, все три из них будут работать, но первый может не всегда работать.

Я подозреваю, что вы просто хотите дополнительное NULL сравнения:

SELECT t1.DateFull, COUNT(t2.ContainerWashedDate) as Washes 
FROM DateLookup t1 LEFT JOIN 
    factContainerWash t2 
    ON t1.Datefull = t2.ContainerWashedDate 
WHERE t1.DateFull >= '2016-10-05' and 
     t1.DateFull <= '2016-11-09' and 
     (t2.createdBy <> 21 or t2.createdBy is null) 
GROUP BY t1.DateFull 
ORDER BY DateFull; 

Или, как вариант, использовать условную агрегацию:

SELECT t1.DateFull, 
     COUNT(CASE WHEN createdBy <> 21 THEN t2.ContainerWashedDate END) as Washes 
FROM DateLookup t1 LEFT JOIN 
    factContainerWash t2 
    ON t1.Datefull = t2.ContainerWashedDate 
WHERE t1.DateFull >= '2016-10-05' and 
     t1.DateFull <= '2016-11-09' 
GROUP BY t1.DateFull 
ORDER BY DateFull; 

Это также возможно, что перемещение условия к статье ON делает Вам необходимо:

SELECT t1.DateFull, 
     COUNT(t2.ContainerWashedDate) as Washes 
FROM DateLookup t1 LEFT JOIN 
    factContainerWash t2 
    ON t1.Datefull = t2.ContainerWashedDate AND t2.createdBy <> 21 
WHERE t1.DateFull >= '2016-10-05' and 
     t1.DateFull <= '2016-11-09' 
GROUP BY t1.DateFull 
ORDER BY DateFull; 
+1

Я нашел ваш второй подход к работе лучше всего для меня. –

2

Когда вы использовал t2.CreatedBy в предложении WHERE, вы сделали LEFT JOIN ставкой INNER JOIN. Как насчет чего-то вроде этого:

SELECT 
    t1.DateFull 
    , COALESCE(t2.Washes, 0) AS Washes 
FROM 
    (
    SELECT 
     ContainerWahsedDate 
     , COUNT(ContainerWahsedDate) AS Washes 
    FROM 
     factConainerWash 
    WHERE 
     ContainerWahsedDate BETWEEN '2016-10-05' AND '2016-11-09' 
     AND CreatedBy <> 21 
    GROUP BY 
     ContainerWashedDate 
    ) t2 
    LEFT JOIN DateLookup t1 ON t1.DateFull = t2.ContainerWahsedDate 
WHERE 
    t2.DateFull BETWEEN '2016-10-05' AND '2016-11-09'