MySQL计数返回0而不是没有记录

时间:2013-12-11 15:45:26

标签: mysql sql

我在Stackoverflow上搜索过这个答案,但我无法让任何已发布的解决方案适合我。

我有两张桌子:

builds:
build_id (INT)
status_id (INT)
created (INT)

statuses:
status_id (INT)
name (VARCHAR)
description (VARCHAR)

我想要一个查询,它将返回日期,构建状态以及该日期和状态的计数。如果特定状态的计数为0,我希望它返回0.例如:

+------------+-------+----------+
| date       | count | name     |
+------------+-------+----------+
| 2013-12-05 |     1 | Failed   |
| 2013-12-05 |     2 | Stable   |
| 2013-12-05 |     1 | Unstable |
| 2013-12-06 |     0 | Failed   |
| 2013-12-06 |     1 | Stable   |
| 2013-12-06 |     1 | Unstable |
+------------+-------+----------+

我在我的sql查询中尝试了各种左连接和ifnull组合。以下是不带0计数返回结果的查询:

SELECT FROM_UNIXTIME(created, '%Y-%m-%d') as date,
COUNT(statuses.status_id) as count, statuses.name
FROM builds
LEFT JOIN statuses on builds.status_id=statuses.status_id
GROUP BY date, name;

此查询显示:

+------------+-------+----------+
| date       | count | name     |
+------------+-------+----------+
| 2013-12-05 |     1 | Failed   |
| 2013-12-05 |     2 | Stable   |
| 2013-12-05 |     1 | Unstable |
| 2013-12-06 |     2 | Stable   |
| 2013-12-06 |     1 | Unstable |
+------------+-------+----------+

提前谢谢。

值得一提的是,此处发布的解决方案有效:MySQL Group by - Get columns with zero count

除了他们需要where子句中的公司名称(在我的情况下的日期字段)...我想在一个查询中获得所有日期的列表。

3 个答案:

答案 0 :(得分:0)

尝试:

SELECT FROM_UNIXTIME(created, '%Y-%m-%d') as date,
       COUNT(builds.status_id) as count, 
       statuses.name
FROM builds
RIGHT JOIN statuses on builds.status_id=statuses.status_id
GROUP BY date, name;

或者也许:

SELECT FROM_UNIXTIME(created, '%Y-%m-%d') as date,
       SUM(CASE WHEN builds.status_id IS NULL THEN 0 ELSE 1 END ) as count, 
       statuses.name
FROM builds
RIGHT JOIN statuses on builds.status_id=statuses.status_id
GROUP BY date, name;

COUNT(列)理论上应该只计算非空值,但谁知道......

答案 1 :(得分:0)

尝试右连接:

SELECT FROM_UNIXTIME(created, '%Y-%m-%d') as date,
COUNT(statuses.status_id) as count, statuses.name
FROM builds
RIGHT JOIN statuses on builds.status_id=statuses.status_id
GROUP BY date, name;

答案 2 :(得分:0)

我最后通过加入一个类似于这篇文章中建议的单独日历表来完成这项工作:SQL left joining multiple tables

以下是完整查询:

"SELECT 
  allRecords.date,
  allRecords.Name,
  ( SELECT 
      COUNT(statuses.status_id)
    FROM statuses, builds, calendar
    WHERE builds.status_id = statuses.status_id
      AND FROM_UNIXTIME(builds.created, '%Y-%m-%d') = calendar.date
      AND calendar.date = allRecords.date
      AND statuses.name = allRecords.Name
  ) as Count

FROM 
  ( SELECT calendar.date,
      statuses.status_id,
      statuses.name
    FROM
      calendar,
      statuses
    ORDER BY
      calendar.date,
      statuses.name  ) allRecords

LEFT JOIN builds
  ON builds.status_id =  allRecords.status_id

LEFT JOIN statuses
  ON builds.status_id = statuses.status_id

WHERE allRecords.date BETWEEN 
  (SELECT MIN(FROM_UNIXTIME(builds.created, '%Y-%m-%d')) FROM builds) 
AND 
  (SELECT MAX(FROM_UNIXTIME(builds.created, '%Y-%m-%d')) FROM builds)

GROUP BY
  allRecords.date,
  allRecords.Name

ORDER BY 
  allRecords.date,
  CASE allRecords.Name
    WHEN 'Stable' THEN 1
    WHEN 'Unstable' THEN 2
    WHEN 'Failed' THEN 3
  ELSE 100 END";