【问题标题】:MySQL show count of 0 for dates with no records对于没有记录的日期,MySQL 显示计数为 0
【发布时间】:2014-06-19 07:40:48
【问题描述】:

我正在尝试通过当前一周(过去 7 天)的列表获取所有用户尝试的 COUNT

此查询有效,但如果日期不存在则不返回 0:

SELECT COUNT(*) AS attempt_count, 
    DATE_FORMAT(attempt_date,'%Y/%m/%d') AS attempt_date 
FROM users_attempts 
WHERE DATE_SUB(attempt_date, INTERVAL 1 DAY) > DATE_SUB(DATE(NOW()), INTERVAL 1 WEEK) 
GROUP BY DAY(attempt_date) DESC;

这个查询返回当前最后一周每天所有尝试的 COUNT,我得到了这个(我只有 1 条记录):

attempt_count | attempt_date
1               2014/06/19

我想要这个结果:

attempt_count | attempt_date
1               2014/06/19
0               2014/06/18
0               2014/06/17
0               2014/06/16
0               2014/06/15
0               2014/06/14
0               2014/06/13

非常感谢

演示http://sqlfiddle.com/#!2/b58bb/1/0

【问题讨论】:

  • 数据库中有那些 0 的日期吗?如果没有,那么您需要使用以下技术来获取结果中缺少的日期stackoverflow.com/questions/23300303/…
  • 你可以离开加入一个日历表,每天一行,你的查询得到适当的结果
  • @mc110 我没有任何日历表。
  • 制作一个。 SELECT 语句不会首先创建不在数据库中的数据。您可以在客户端执行此操作,也可以在存储过程中执行此操作。但是,如果您想让 SELECT 生成这些日期,则需要将它们放在某个表中。
  • @Frazz 你是对的,但我正在尝试 Abhik Chakraborty 的技术,创建一个临时日历表,我认为是可能的。

标签: mysql sql date count


【解决方案1】:

好吧,我之前在MySql Single Table, Select last 7 days and include empty rows的回答中回答了

这里你可以做些什么来动态选择日期

select 
t1.attempt_date,
coalesce(SUM(t1.attempt_count+t2.attempt_count), 0) AS attempt_count
from
(
  select DATE_FORMAT(a.Date,'%Y/%m/%d') as attempt_date,
  '0' as  attempt_count
  from (
    select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
  ) a
  where a.Date BETWEEN NOW() - INTERVAL 7 DAY AND NOW()
)t1
left join
(
  SELECT DATE_FORMAT(attempt_date,'%Y/%m/%d') AS attempt_date, 
  COUNT(*) AS attempt_count
  FROM users_attempts
  WHERE DATE_SUB(attempt_date, INTERVAL 1 DAY) > DATE_SUB(DATE(NOW()), INTERVAL 1 WEEK) 
  GROUP BY DAY(attempt_date) DESC
)t2
on t2.attempt_date = t1.attempt_date
group by DAY(t1.attempt_date)
order by t1.attempt_date desc;

DEMO

【讨论】:

  • 完美,完美运行,非常感谢@Abhik Chakraborty
【解决方案2】:

创建一个日历表,或者您可以尝试:

SELECT COUNT(*) AS attempt_count,
       DATE_FORMAT(ca_date,'%Y/%m/%d') AS attempt_date
FROM
  (SELECT STR_TO_DATE('2014/06/19', '%Y/%m/%d') ca_date
   UNION ALL SELECT STR_TO_DATE('2014/06/18', '%Y/%m/%d') ca_date
   UNION ALL SELECT STR_TO_DATE('2014/06/17', '%Y/%m/%d') ca_date
   UNION ALL SELECT STR_TO_DATE('2014/06/16', '%Y/%m/%d') ca_date
   UNION ALL SELECT STR_TO_DATE('2014/06/15', '%Y/%m/%d') ca_date
   UNION ALL SELECT STR_TO_DATE('2014/06/14', '%Y/%m/%d') ca_date
   UNION ALL SELECT STR_TO_DATE('2014/06/13', '%Y/%m/%d') ca_date) AS calendar
LEFT JOIN users_attempts ON users_attempts.attempt_date = calendar.ca_date
GROUP BY calendar.ca_date
ORDER BY calendar.ca_date DESC;

【讨论】:

  • 这对于一周来说太具体了。相反,您应该使用更好的日历。
  • 不需要从 date 重新转换为 date_format
  • 感谢您的评论。只是尝试让他知道需要做什么。 date_format 用于演示。
  • 不错的答案,但这不是一个动态的一周,但我需要从当天开始的最后 7 天
猜你喜欢
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
  • 2017-04-29
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多