按日期选择min(start_time),max(end_time)组

时间:2017-01-19 10:30:36

标签: mysql date datetime

我有一张表看起来像这样

Board

我希望我的结果看起来像

start_time                end_time 
2016-10-26 08:45:00       2016-10-27 09:45:00
2016-10-26 09:45:00       2016-10-26 10:45:00
2016-10-27 07:45:00       2016-10-27 11:45:00
请帮助我

编辑

start_time                end_time 
2016-10-26 08:45:00       2016-10-26 10:45:00
2016-10-27 07:45:00       2016-10-27 11:45:00

但是当开始时间和结束时间没有在同一天发生时,它会一直显示错误的结果。

1 个答案:

答案 0 :(得分:0)

SELECT
    MIN(startDate.start_time) AS start_time,
    MAX(endDate.end_time) AS end_time
FROM
    dates AS startDate
LEFT JOIN dates AS endDate
        ON DATE_FORMAT(startDate.start_time, '%Y-%m-%d') = DATE_FORMAT(endDate.end_time, '%Y-%m-%d')
GROUP BY
    DATE_FORMAT(startDate.start_time, '%Y-%m-%d');

因为start_time和end_time总是在同一天发生,你必须加入end_times然后查找当天的最新时间。

这个可能会在index上使用end_time。如果列上有index,您应该尝试查找它。

SELECT
    MIN(startDate.start_time) AS start_time,
    MAX(endDate.end_time) AS end_time
FROM
    dates AS startDate
LEFT JOIN dates AS endDate
        ON endDate.end_time BETWEEN DATE_FORMAT(startDate.start_time, '%Y-%m-%d 00:00:00') AND DATE_FORMAT(startDate.start_time, '%Y-%m-%d 23:59:59')
GROUP BY
    DATE_FORMAT(startDate.start_time, '%Y-%m-%d');

示例 Fiddle with the steps

我将稍微更改您的示例数据,以便您了解我选择使用join获取end_time的原因。我们将专注于 2016-10-26 的日期。

结果将与您的示例相同:

start_time                end_time 
2016-10-26 08:45:00       2016-10-26 10:45:00

我们有以下数据。如您所见,结果中的值位于原始数据的不同行中。第一行中start_time的值,第二行中end_time的值。

start_time                end_time 
2016-10-26 08:45:00       2016-10-27 09:45:00
2016-10-27 09:45:00       2016-10-26 10:45:00
2016-10-27 07:45:00       2016-10-27 11:45:00
2016-10-26 10:30:00       2016-10-26 10:40:00

第一步 - 准备数据

第一步是将匹配的end_time与start_times匹配。因此,对于我们的数据集,end_times的日期为2016-10-26。

为此,我们join格式化datetime列,以便删除时间。我们转向" 2016-10-26 10:40:00"进入" 2016-10-26"。

SELECT
    startDate.start_time AS start_time,
    endDate.end_time AS end_time
FROM
    dates AS startDate
LEFT JOIN dates AS endDate
        ON DATE_FORMAT(startDate.start_time, '%Y-%m-%d') = DATE_FORMAT(endDate.end_time, '%Y-%m-%d')

这为我们提供了一些在start_time和end_time列上具有相同日期的行。它是start_time和end_time的笛卡尔积,限于同一天。

+---------------------+---------------------+
| start_time          | end_time            |
+---------------------+---------------------+
| 2016-10-26 08:45:00 | 2016-10-26 10:45:00 |
| 2016-10-26 08:45:00 | 2016-10-26 10:40:00 |
| 2016-10-27 09:45:00 | 2016-10-27 09:45:00 |
| 2016-10-27 09:45:00 | 2016-10-27 11:45:00 |
| 2016-10-27 07:45:00 | 2016-10-27 09:45:00 |
| 2016-10-27 07:45:00 | 2016-10-27 11:45:00 |
| 2016-10-26 10:30:00 | 2016-10-26 10:45:00 |
| 2016-10-26 10:30:00 | 2016-10-26 10:40:00 |
+---------------------+---------------------+

第二步 - 按天分组

现在我们可以简单地对它进行分组,我们再次只想使用日期时间字段的日期,因此我们对其进行格式化以便时间被删除。

SELECT
    startDate.start_time AS start_time,
    endDate.end_time AS end_time
FROM
    dates AS startDate
LEFT JOIN dates AS endDate
        ON DATE_FORMAT(startDate.start_time, '%Y-%m-%d') = DATE_FORMAT(endDate.end_time, '%Y-%m-%d')
GROUP BY
    DATE_FORMAT(startDate.start_time, '%Y-%m-%d')

这将给我们一些随机的结果集*,它按天分组。

  • 如果数据的顺序正确,它甚至可能看起来是正确的结果......危险。您可以在小提琴中看到它,2016-10-26的数据是为了显示正确的'结果,2016-10-27的数据不是。

  • 此查询也可能会给您一个错误,因为您选择的是非聚合列和非聚类列 - 取决于您的mysql版本和配置

最后一步 - 获取正确的数据

为了获得正确的结果,我们现在使用聚合函数MIN()MAX()

SELECT
    MIN(startDate.start_time) AS start_time,
    MAX(endDate.end_time) AS end_time
FROM
    dates AS startDate
LEFT JOIN dates AS endDate
        ON DATE_FORMAT(startDate.start_time, '%Y-%m-%d') = DATE_FORMAT(endDate.end_time, '%Y-%m-%d')
GROUP BY
    DATE_FORMAT(startDate.start_time, '%Y-%m-%d')

+---------------------+---------------------+
| start_time          | end_time            |
+---------------------+---------------------+
| 2016-10-26 08:45:00 | 2016-10-26 10:45:00 |
| 2016-10-27 07:45:00 | 2016-10-27 11:45:00 |
+---------------------+---------------------+