MySQL COUNT return 0 如果它不为空
MySQL COUNT return 0 if it's not null
我需要统计日期之间的所有文章。我使用 IFNULL(COUNT(*), 0)
其中 returns 为空。
SELECT posts_count, dates.fulldate
FROM dates
LEFT JOIN
(SELECT IFNULL(COUNT(post_id), 0) AS posts_count, DATE_FORMAT(post_created_at, "%Y-%m-%d") AS pdate
FROM posts
WHERE DATE_FORMAT(post_created_at, "%Y-%m-%d") BETWEEN NOW() - INTERVAL 31 DAY AND NOW()
GROUP BY DATE_FORMAT(post_created_at, "%Y-%m-%d")) t
ON t.pdate = dates.fulldate
WHERE dates.fulldate BETWEEN CURDATE() - INTERVAL 31 DAY AND CURDATE() ORDER BY dates.fulldate ASC;
The result is:
NULL | 2020-05-20
NULL | 2020-05-21
NULL | 2020-05-22
7634 | 2020-05-23
51224 | 2020-05-24
The result I want its:
0 | 2020-06-16
1233 | 2020-06-15
4354 | 2020-06-14
0 | 2020-06-13
0 | 2020-06-12
您需要在主查询而不是子查询中执行 IFNULL()
。子查询没有为缺失的日期返回任何行,因此甚至没有要转换为 0 的空计数。
SELECT IFNULL(posts_count, 0) AS posts_count, dates.fulldate
FROM dates
LEFT JOIN
(SELECT COUNT(*) AS posts_count, DATE_FORMAT(post_created_at, "%Y-%m-%d") AS pdate
FROM posts
WHERE DATE_FORMAT(post_created_at, "%Y-%m-%d") BETWEEN NOW() - INTERVAL 31 DAY AND NOW()
GROUP BY DATE_FORMAT(post_created_at, "%Y-%m-%d")) t
ON t.pdate = dates.fulldate
WHERE dates.fulldate BETWEEN CURDATE() - INTERVAL 31 DAY AND CURDATE()
ORDER BY dates.fulldate ASC;
您的查询似乎比需要的更复杂。我没有看到按日期分组 post 和在日期上过滤两次的子查询的意义。
我觉得你想要的逻辑是:
select count(p.post_id) post_count, d.fulldate
from dates d
left join posts p
on p.post_created_at >= d.fulldate
and p.post_created_at < d.fulldate + interval 1 day
where d.fulldate >= current_date - interval 1 month
group by d.fulldate
order by d.fulldate
我希望这应该比您的原始代码更有效率,尤其是因为未在 post 日期列上应用日期函数。我会推荐 posts(post_created_at)
上的索引以充分利用此代码。
我需要统计日期之间的所有文章。我使用 IFNULL(COUNT(*), 0)
其中 returns 为空。
SELECT posts_count, dates.fulldate
FROM dates
LEFT JOIN
(SELECT IFNULL(COUNT(post_id), 0) AS posts_count, DATE_FORMAT(post_created_at, "%Y-%m-%d") AS pdate
FROM posts
WHERE DATE_FORMAT(post_created_at, "%Y-%m-%d") BETWEEN NOW() - INTERVAL 31 DAY AND NOW()
GROUP BY DATE_FORMAT(post_created_at, "%Y-%m-%d")) t
ON t.pdate = dates.fulldate
WHERE dates.fulldate BETWEEN CURDATE() - INTERVAL 31 DAY AND CURDATE() ORDER BY dates.fulldate ASC;
The result is:
NULL | 2020-05-20
NULL | 2020-05-21
NULL | 2020-05-22
7634 | 2020-05-23
51224 | 2020-05-24
The result I want its:
0 | 2020-06-16
1233 | 2020-06-15
4354 | 2020-06-14
0 | 2020-06-13
0 | 2020-06-12
您需要在主查询而不是子查询中执行 IFNULL()
。子查询没有为缺失的日期返回任何行,因此甚至没有要转换为 0 的空计数。
SELECT IFNULL(posts_count, 0) AS posts_count, dates.fulldate
FROM dates
LEFT JOIN
(SELECT COUNT(*) AS posts_count, DATE_FORMAT(post_created_at, "%Y-%m-%d") AS pdate
FROM posts
WHERE DATE_FORMAT(post_created_at, "%Y-%m-%d") BETWEEN NOW() - INTERVAL 31 DAY AND NOW()
GROUP BY DATE_FORMAT(post_created_at, "%Y-%m-%d")) t
ON t.pdate = dates.fulldate
WHERE dates.fulldate BETWEEN CURDATE() - INTERVAL 31 DAY AND CURDATE()
ORDER BY dates.fulldate ASC;
您的查询似乎比需要的更复杂。我没有看到按日期分组 post 和在日期上过滤两次的子查询的意义。
我觉得你想要的逻辑是:
select count(p.post_id) post_count, d.fulldate
from dates d
left join posts p
on p.post_created_at >= d.fulldate
and p.post_created_at < d.fulldate + interval 1 day
where d.fulldate >= current_date - interval 1 month
group by d.fulldate
order by d.fulldate
我希望这应该比您的原始代码更有效率,尤其是因为未在 post 日期列上应用日期函数。我会推荐 posts(post_created_at)
上的索引以充分利用此代码。