使用LEFT JOIN的MySQL查询不会返回空结果

BN83

我创建了一个日历表,其中仅包含许多日期。然后,我的活动表中的日期会对齐,如果一天没有活动,我想为此返回零。我有以下内容:

SELECT cDate, Branch, IFNULL(COUNT(*),0) as count
FROM Events E LEFT JOIN Calendar C ON C.cDate = DATE(E.eventDate)
WHERE cDate BETWEEN '2018-04-14' AND '2018-04-18'
GROUP BY Branch, cDate
ORDER BY cDate

但是结果目前显示:

  cDate    | Branch | count
2018-04-14 |   1    |  5
2018-04-14 |   2    |  4
2018-04-16 |   1    |  1
2018-04-16 |   2    |  3
2018-04-17 |   1    |  5
2018-04-18 |   1    |  4

但是我打算让它显示任何计数为零的日期,如下所示:

  cDate    | Branch | count
2018-04-14 |   1    |  5
2018-04-14 |   2    |  4
2018-04-15 |   1    |  0
2018-04-15 |   2    |  0
2018-04-16 |   1    |  1
2018-04-16 |   2    |  3
2018-04-17 |   1    |  5
2018-04-17 |   2    |  0
2018-04-18 |   1    |  4
2018-04-18 |   2    |  0
spencer7593

WHERE子句中要求外部联接表中的列为非NULL的任何条件有效地“否定”联接的外部性,使其等效于内部联接。

这种情况

   cdate BETWEEN '2018-04-14' AND '2018-04-18'

只有具有非NULL值的行才能满足cdate

这样可以帮助我思考左外部联接操作:

当左边的一行没有右边的匹配行时,在右边发明了一个虚拟行作为匹配行。(联接需要匹配的行,以便可以返回该行。)生成/发明的虚拟行完全由NULL组成

因此,要解决的部分问题是将该条件从WHERE子句重新定位ON外部联接子句中。

解决此问题可能是解决问题所需的全部,但是...我犹豫要特别建议将其作为解决方案,因为我对实际的规范不了解。


另一个建议:

为了帮助将来的读者,请考虑对所有列引用进行限定(我们注意到该SQL语句已经为表分配了别名。)

根据问题中发布的信息,我们无法确定该branch列来自哪个表看起来Calendar可能只是唯一日期的列表,所以我们将假定branchEvent表中找到该列。


我怀疑期望的结果将通过如下查询返回:

SELECT c.cdate
     , b.branch
     , COUNT(e.branch)  AS `count`
  FROM Calendar c
 CROSS
  JOIN Branch b 

  LEFT
  JOIN Events e
    ON e.eventdate  >= c.cdate
   AND e.eventdate   < c.cdate + INTERVAL 1 DAY
   AND e.branch      = b.branch

 WHERE c.cdate BETWEEN '2018-04-14' AND '2018-04-18'
 GROUP
    BY c.cdate
     , b.branch
 ORDER
    BY c.cdate
     , b.branch

让我们打开包装。

我们正在从中获取指定范围内的所有日期Calendar(我们怀疑/假设这cdate是DATE数据类型,并且保证是唯一的。在此查询中,我们基本上是在使用它Calendar来生成一组连续的日期值。)

而且我们想从中获取Events与每个特定日期相关的数目的“计数” Calendar

请注意,COUNT()聚合将返回非NULL值;如果我们要计算一个计算结果为NULL的表达式,则该计数不会增加。我们不需要将COUNT()聚合包装在IFNULL / COALESCE / CASE中,以将NULL替换为零。

我们正在做“左联接”。这意味着我们希望驱动表(Calendar在本例中)位于左侧,而我们希望从中找到匹配项的表位于右侧如果匹配行右侧发现,包括所有NULL值的虚设行将被“生成”,所以加入行可以返回。

由于我们要通过“ cdate”和“ branch来获取计数,因此我们还需要“ branch”值的行源(如@Shadow所述,我们可以使用表格代替内联视图b内联视图的目的b是获取branch我们要返回的不同列表。)

CROSS JOIN将使我们获得交叉产品。也就是说,所有cdate值都与所有值匹配branch,因此我们有一个完整的集合。五个cdate值,两个branch值,使我们得到一组10行,即我们要返回的行。Event给定cdate没有匹配的行时,我们需要这些行能够返回“零”计数branch

再一次,我们假设在中cdate是唯一的Calendar,因此我们从返回(最多)五行Calendar我们还假设会有(潜在)从更多的行Event要检查需要,比较eventdatecdate我们不想阻止MySQL有效地利用列的索引范围操作eventdate(有合适的​​索引),因此我们避免将eventdate包装在函数中,而是引用裸列。


我们只是在猜测需求,因此我的建议可能无法满足实际要求。


跟进

我们需要一个行源作为branch值。可以是表,也可以是内联视图查询。原始SQL并未假设使用Branch表,因此我们使用查询来获取不同的分支列表:

  JOIN  ( SELECT br.branch
           FROM Events br
          GROUP BY br.branch
       ) b

我的原始答案中的内联视图查询的作用与Branch修改后的查询中相同它返回表中branch出现的不同列表Events如果有一个索引branch作为前导列,则MySQL可以使用该索引。

最大的区别branch在于Branch中出现但表中未出现值(例如3)Event使用的内联视图Event,我们将不会返回branch= 3的任何行

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

使用限制和偏移量的MySQL查询不会返回预期的有序结果

MySQL查询执行正常,但使用!= NULL时返回空结果集(假)。

使用INNER JOIN排除MYSQL查询结果

MySQL-使用LEFT JOIN会产生意外结果

SQL Left Join不会返回所有结果

从两个具有空LEFT JOIN的表中选择的SQLAlchemy返回空结果

查询无法与LEFT JOIN(MySQL)一起正常使用

COUNT返回带有NULL的LEFT JOIN查询的模糊结果

当对NULL列使用WHERE子句时,mySQL select查询不会返回结果。

MySQL IS LE NULL的LEFT JOIN返回空结果

mysql如何使用join和left join

使用Dapper的Sql查询返回空结果,但分析器的请求结果不为空

使用INNER JOIN的mySQL查询的打印结果

使用WHERE子句的MySQL LEFT JOIN查询

MySQL乘以查询结果(LEFT JOIN,SUM,COUNT,GROUP BY)

使用LEFT JOIN和History表的MySQL查询的正确结果

使用COUNT ON LEFT JOIN进行MySQL查询

MySQL-如何改善使用多个LEFT JOIN的复杂查询

使用LEFT OUTER JOIN建立查询结果

MySQL查询的排序结果(使用join)

LEFT JOIN查询返回双精度结果

如果在 LEFT JOIN 和 WHERE 子句中找不到结果,如何在 MySQL 查询中返回 NULL 值

使用 LEFT JOIN 查询 MongoDB

使用 JOIN 表的错误 MySQL 查询结果

从 2 LEFT JOIN mysql 查询中获取连接结果

使用 _PARTITIONDATE LEFT JOIN

Postgres LEFT JOIN 不返回空值?

MYSQL 查询使用 LEFT JOIN 填充数据空白

LEFT JOIN 查询仅返回表 2 中存在的结果