Full Outer Join 不包括双方的所有记录

Posted

技术标签:

【中文标题】Full Outer Join 不包括双方的所有记录【英文标题】:Full Outer Join Not including all records from both sides 【发布时间】:2019-10-21 20:50:34 【问题描述】:

我有一个日期从 2000 年到 2029 年的日历表。我在 date=tdate 对我的数据表进行了完全外部联接。我的目标是按日期计算行程,如果没有行程则显示零。但是,所有日期都没有显示。如果数据表中没有行程日期,则日历表中的日期根本不会显示。我以前从未见过这种情况。我尝试将其更改为也不起作用的左外连接。实际查询如下。

    SELECT DISTINCT c.DATE,
        COALESCE(COUNT(t.TripID), 0) AS tripCount
    FROM dbo.Calendar c
    FULL OUTER JOIN dbo.TripsMade t ON c.DATE = CONVERT(DATE, t.tripdate, 126)
    WHERE (c.DATE BETWEEN '2019-09-01' AND '2019-09-30' )
      AND (t.compid = 270 OR t.compid IS NULL)
    GROUP BY c.DATE
    ORDER BY c.DATE

如果我从日历表中选择所有日期,它们都在那里。数据表中缺少日期,并且总是会丢失一些日期。我需要所有日期都显示在此报告中,如果数据表端没有相关记录,则显示零。

我在这里错过了什么?

目标 日期           TOTAL_TRIPS 2019-09-01             3 2019-09-02             5 2019-09-03             0 2019-09-04             4 2019-09-05             0 2019-09-06             9

【问题讨论】:

您的 WHERE 将其转换为隐式 INNER JOIN,因为未处理 c.DateNULL 值。 t.compid=270 也应该在ON 中,然后你可以删除t.compid IS NULL 【参考方案1】:

您的WHERE 子句最终从两个表中过滤掉不匹配项,几乎将它们变成INNER JOINs(t 上的条件有点复杂。

我认为您不需要FULL JOIN。我怀疑您想要在ON 子句中使用过滤(用于第二个表)的LEFT JOIN

SELECT c.Date, COUNT(t.TripID) AS tripCount
FROM dbo.Calendar c LEFT OUTER JOIN
     dbo.TripsMade t
     ON c.date = CONVERT(DATE, t.tripdate, 126) AND
        t.compid = 270
WHERE c.Date BETWEEN '2019-09-01' AND '2019-09-30'
GROUP BY c.Date
ORDER BY c.Date;

如果compid 实际上可以采用NULL 值并且您想要它们,那么使用(t.compid = 270 OR t.compid IS NULL)。不过,我怀疑这不是您想要的。 NULL 仅代表 JOIN 上的不匹配。

注意事项:

SELECT DISTINCT 几乎GROUP BY 一起使用,在这种情况下不需要。 COUNT() 不返回NULL,因此不需要COALESCE()。 对first表的过滤确实属于WHERE子句。

【讨论】:

以上是关于Full Outer Join 不包括双方的所有记录的主要内容,如果未能解决你的问题,请参考以下文章

FULL OUTER JOIN 不返回所有表的内容

如何在 MySQL 中进行 FULL OUTER JOIN?

如何在 MySQL 中进行 FULL OUTER JOIN?

如何在 MySQL 中进行 FULL OUTER JOIN?

SQL的JOIN语法解析(inner join, left join, right join, full outer join的区别)

MYSQL FULL OUTER JOIN - 使用 LEFT-UNION-LEFT JOIN 时的所有 NULL 结果