mySQL查询不跳过"空"结果

时间:2017-06-30 16:08:30

标签: php mysql

我有这样的查询

SELECT count(Distinct name) as total, DATE_FORMAT(date_added, '%M %d, %Y') AS date_added 
FROM `submitted_changes` 
WHERE date_added >= NOW() - INTERVAL 1 WEEK 
GROUP BY DATE(date_added)

它工作得很好,并返回具有格式良好的日期和总数的行。基本上,这表示每天提交的数量。

我遇到的问题是处理提交0天的日子。我现在不想跳过这些日子,而是显示日期,total为0。有没有办法确保当我执行上面的查询(仅包括过去一周[7天]的日期)时,我总会得到7行?

1 个答案:

答案 0 :(得分:1)

要执行此操作,您需要每个日期都存在记录。由于您的submitted_changes表格不是这种情况 - 我建议您创建一个日期表(如果您还没有)。

注意 - 对于最短的版本,请检查底部的最后一次编辑:

以下是临时表的示例。首先运行:

CREATE TEMPORARY TABLE IF NOT EXISTS dates AS 
SELECT DATE(curdate()-num) as date_col
FROM
(
SELECT 0 as num
UNION
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6) sub

这将创建一个包含7个相关日期的表。 现在left join包含您的数据:

SELECT 
      count(Distinct name) as total,
      DATE_FORMAT(date_col, '%M %d, %Y') AS date_added 
FROM dates LEFT JOIN submitted_changes 
               on (dates.date_col = DATE(submitted_changes.date_added))
GROUP BY date_col

您也可以将其作为一次性查询(没有create语句)运行:

SELECT 
      count(Distinct name) as total,
      DATE_FORMAT(date_col, '%M %d, %Y') AS date_added 
FROM 
(SELECT DATE(curdate()-num) as date_col
FROM
(
SELECT 0 as num
UNION
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6) sub) dates
LEFT JOIN submitted_changes 
               on (dates.date_col = DATE(submitted_changes.date_added))
GROUP BY date_col

另一种方法是永久dim_date 。以下是静态表的示例代码(包含更多额外字段):

CREATE TABLE dim_date (
  id            int(11) NOT NULL AUTO_INCREMENT,
  date      date, 
  day       int(11), 
  month         int(11), 
  year      int(11),
  day_name  varchar(45),
  PRIMARY KEY (id),
  INDEX date_index (date)
)

然后填充它:

SET @currdate := "2015-01-01";
SET @enddate := "2025-01-01";

delimiter $$
DROP PROCEDURE IF EXISTS BuildDate$$
CREATE PROCEDURE BuildDate()
    BEGIN
            WHILE @currdate < @enddate DO
            INSERT INTO dim_date  (date, day, month, year, day_name)
            VALUES (
                    @currdate,  DAY(@currdate),  MONTH(@currdate), 
              YEAR(@currdate), DAYNAME(@currdate)
);
            SET @currdate := DATE_ADD(@currdate, INTERVAL 1 DAY);
END WHILE;
    END$$
CALL BuildDate();

然后,您最终可以使用left join

运行查询
SELECT 
      count(Distinct name) as total,
      DATE_FORMAT(date, '%M %d, %Y') AS date_added 
FROM dim_date LEFT JOIN submitted_changes 
               on (dim_date.date = DATE(submitted_changes.date_added))
WHERE date >= NOW() - INTERVAL 1 WEEK 
GROUP BY date

即使submitted_changes中没有记录,也会为每个日期返回一行。

修改:受this post启发的另一个一次性超短版本:

SELECT 
      count(Distinct name) as total,
      DATE_FORMAT(date, '%M %d, %Y') AS date_added 
(SELECT date(curdate()-id%7) as date
FROM submitted_changes
GROUP BY num) dates LEFT JOIN submitted_changes 
              on (date.dates = DATE(submitted_changes.date_added))
GROUP BY date