如何在我的查询中包含遗失的日期?

时间:2018-04-11 12:29:48

标签: mysql

下面是我目前使用的mySQL查询

SELECT Date( timestamp ) AS day, Count(id) AS total 
FROM goals_data 
WHERE company = 1
AND Date( timestamp ) BETWEEN Subdate( Curdate( ) , 10 ) AND Curdate( ) 
GROUP BY day desc

为了从mySQL获取输出:

2018-04-09 ------ 3
2018-04-08 ------ 6
2018-04-07 ------ 2
2018-04-05 ------ 4

问题在于,正如您从上面的示例输出中看到的那样,没有2018-04-06,因为当天没有任何条目。

我想要实现的是即使没有找到条目,也会产生数天的后果。

所以最佳的是:

2018-04-09 ------ 3
2018-04-08 ------ 6
2018-04-07 ------ 2
2018-04-06 ------ 0
2018-04-05 ------ 4

如何通过编辑查询来完成此操作?

2 个答案:

答案 0 :(得分:1)

正如我的评论中提到的并且正如其他人所建议的那样,您需要在MySQL中生成日期范围。

使用answer I marked as a duplicate to generate the date range,您可以将查询添加为LEFT JOIN以检索结果集总计,将生成的日期与goals_data时间戳匹配,移动{{1}子查询的标准。

company

产生:http://www.sqlfiddle.com/#!9/17f03f/2

SELECT a.Date as day, COUNT(gd.id) AS total
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
LEFT JOIN (SELECT * FROM goals_data WHERE company = 1) AS gd
ON DATE(gd.`timestamp`) = DATE(a.Date)
WHERE DATE(a.Date) BETWEEN SUBDATE(CURDATE(), INTERVAL 10 DAY) AND CURDATE()
GROUP BY day DESC;

或者,正如我在评论中建议的那样,您可以使用PHP为报告生成所需的日期范围。

|        day | total |
|------------|-------|
| 2018-04-11 |     0 |
| 2018-04-10 |     0 |
| 2018-04-09 |     3 |
| 2018-04-08 |     6 |
| 2018-04-07 |     2 |
| 2018-04-06 |     0 |
| 2018-04-05 |     4 |
| 2018-04-04 |     0 |
| 2018-04-03 |     0 |
| 2018-04-02 |     0 |
| 2018-04-01 |     0 |

产生相同的结果:https://3v4l.org/YrpU8

$interval = new \DateInterval('P10D');
$currentDate = new \DateTime;
$previousDate = clone $currentDate;
$previousDate->sub($interval);
/*
$query = 'SELECT Date( timestamp ) AS day, Count(id) AS `count`
FROM goals_data 
WHERE company = 1
AND Date( timestamp ) BETWEEN :previous_date AND :current_date
GROUP BY day desc'
*/
$dbDates = array_column($dbRows, null, 'day');
$period = new \DatePeriod($currentDate, DateInterval::createFromDateString('-1 day'), $interval->d);
foreach ($period as $date) {
    $key = $date->format('Y-m-d');
    if (!array_key_exists($key, $dbDates)) {
        $dbDates[$key] = ['day' => $key, 'count' => 0];
    }
    echo $dbDates[$key]['day'] . ' ----- ' . $dbDates[$key]['count'] . \PHP_EOL;
}

答案 1 :(得分:0)

我之前通过使用已包含日期范围的单独表格/查询来实现此目的。然后,您可以在日期表中保持连接,以便包含所有日期以及右表中的匹配值。