T-SQL:如何保持左连接但过滤查询

T-SQL: How to keep left join but filter query

我正在尝试过滤掉由特定用户添加的结果,同时保留每一天,因为此查询将用于报告中的图表。当我删除 t2.createdBy <> 21 时,我得到了所有日期,但我还需要由此过滤的结果是正确的。

查询:

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

以下是三种方法。当我开始回答这个问题时,我意识到可能会发生一些微妙的不同的事情。可能所有这三个都有效,但第一个可能并不总是有效。

我怀疑您只是想要一个额外的 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;

当您在 WHERE 子句中使用 t2.CreatedBy 时,您使 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'