我创建了一个日历表,其中只包含大量的日期。然后,我的events表会列出日期,如果一天中没有事件,我希望返回一个零。我有以下几点:
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
3条答案
按热度按时间vpfxa7rd1#
中的任何条件
WHERE
要求外部联接表中的列为非空的子句有效地“否定”联接的外部性,使其等效于内部联接。这种情况
将仅由具有非空值的行满足
cdate
.它有助于(我)这样思考左外连接操作:
当左侧的行没有右侧的匹配行时,在右侧创建一个虚拟行作为匹配行(连接需要匹配的行,以便可以返回该行。)生成的/虚构的虚拟行完全由
NULL
价值观。因此,对你所观察到的行为的一个部分修正就是将该条件从
WHERE
条款进入ON
外连接的子句。这种改变也许是解决问题所需要的全部,但是。。。我不太愿意具体推荐这个解决方案,因为我不了解实际的规范。
另一项建议:
为了帮助将来的读者,请考虑限定所有列引用(我们注意到sql语句已经为表分配了别名。)
从问题中公布的信息来看,我们无法确定是哪个表
branch
列来自。看起来像Calendar
可能只是一个独特日期的列表,所以我们假设branch
列位于Event
table。我怀疑这样的查询会返回所需的结果:
让我们把它打开一点。
我们得到了指定范围内的所有日期
Calendar
. (我们怀疑/假设cdate
是日期数据类型,并且保证是唯一的。在这个查询中,我们基本上使用Calendar
生成一组连续的日期值。)我们想知道
Events
与每个特定日期相关Calendar
.请注意
COUNT()
aggregate将返回一个非空值;如果我们对计算结果为null的表达式进行计数,则计数不会递增。我们不需要把衣服包起来COUNT()
在ifnull/coalesce/case中聚合以将null替换为零。。我们在做“左连接”。那意味着我们想要驾驶台(
Calendar
在本例中)位于左侧,我们希望从中查找匹配项的表位于右侧。如果右侧没有找到匹配的行,则会“生成”一个包含所有空值的虚拟行,这样就可以返回一个联接行。因为我们想通过
cdate
“和”branch
,我们还需要branch
“价值观(正如@shadow所指出的,我们可以使用一个表来代替内联视图b
. 内联视图的用途b
就是得到一个不同的branch
我们希望返回的值。)这个
CROSS JOIN
会得到一个交叉积。那就是,全部cdate
与所有匹配的值branch
值,所以我们有一个完整的集合。5cdate
值,2branch
值,得到一组10行,我们要返回的行。我们需要这些行能够在没有匹配的情况下返回“零”计数Event
指定行的行数cdate
以及branch
.再说一次,我们假设
cdate
是独一无二的Calendar
,因此我们最多从Calendar
. 我们还假设从Event
将需要检查,比较eventdate
至cdate
. 我们不想阻止mysql有效地使用eventdate
列(有合适的索引可用),因此我们避免 Packageeventdate
列,并改为引用裸列。我们只是猜测要求,所以我的建议可能不符合实际规格。
后续行动
我们需要一个资料来源
branch
价值观。可以是表,也可以是内联视图查询。原始sql没有假设Branch
表,因此我们使用查询来获得分支的不同列表:我的原始答案中的内联视图查询与
Branch
修改后的查询中的表。它返回一个不同的branch
出现在Events
table。如果索引branch
由于前导列可用,mysql可以使用索引。最大的不同是
branch
出现在Branch
表,但不显示在Event
table。具有的内联视图Event
,我们不会为返回任何行branch
= 3.lsmd5eda2#
有两个问题:
日历表有完整的日期列表,因此它应该位于左侧连接的左侧。
你不仅需要完整的日期列表,还需要完整的日期-分支组合列表。
我假设您有一个branchs表来存储分支的完整列表。我在日历表上交叉联接这个,然后在实际事件表上左联接结果:
0g0grzrc3#
我将使用交叉连接来连接日历中所需的日期。然后将其与事件表连接,以获得eventdate的计数。