【问题标题】:Min, Max, Average and Count grouped into 15 minute binsMin、Max、Average 和 Count 分组到 15 分钟的区间
【发布时间】:2014-11-21 08:43:42
【问题描述】:

我有一个 MySQL 查询,由另一个线程中的另一个用户提供,它生成了一个一天的 ANPR Journey 时间结果列表,格式如下:

Plate   Date        Starttime   Endtime    Journey Time
YF10PXE 2014-06-18  10:00:32    10:03:22    00:02:50
KG55GOA 2014-06-18  10:00:39    10:03:25    00:02:46
N380LGN 2014-06-18  10:00:43    10:03:44    00:03:01
X557EFB 2014-06-18  10:01:05    10:03:31    00:02:26
AJ61AOS 2014-06-18  10:01:32    10:41:09    00:39:37
BG58ASO 2014-06-18  10:01:42    10:06:09    00:04:27
HT56ENL 2014-06-18  10:02:21    10:07:27    00:05:06
X449LGS 2014-06-18  10:02:51    11:51:42    01:48:51
KR07DWW 2014-06-18  10:03:19    11:05:45    01:02:26
NA59FKE 2014-06-18  10:03:35    10:44:17    00:40:42
HV13MXY 2014-06-18  10:03:54    10:52:12    00:48:18
HS03FUW 2014-06-18  10:04:35    10:06:19    00:01:44
HX53FKP 2014-06-18  10:06:09    10:06:47    00:00:38
HK11NJU 2014-06-18  10:07:25    10:08:06    00:00:41
HN12OAV 2014-06-18  10:07:56    10:08:51    00:00:55
MM08AZB 2014-06-18  10:08:10    10:08:53    00:00:43
BW57ENK 2014-06-18  10:08:35    10:09:19    00:00:44
AE55LHR 2014-06-18  10:08:35    10:09:18    00:00:43
RV03HMA 2014-06-18  10:09:13    11:07:45    00:58:32
JPO6JEM 2014-06-18  10:10:48    10:11:25    00:00:37
BV62WMP 2014-06-18  10:11:00    10:11:46    00:00:46
X647HBP 2014-06-18  10:12:01    10:18:06    00:06:05
HV13LSJ 2014-06-18  10:12:18    10:12:54    00:00:36
X553UYC 2014-06-18  10:13:29    10:17:51    00:04:22
Y208WGO 2014-06-18  10:13:56    10:23:03    00:09:07

SQL命令如下:

    SELECT 
    A.plate,
    a.date,
    a.time as 'start time',
    b.time as 'end time',
    timediff(B.time, A.time) as 'Journey time'
FROM
    (SELECT 
        x.plate,
            date(x.timestamp) as 'date',
            time(x.timestamp) as 'time',
            COUNT(*) rank
    FROM
        anpr_1 x
    JOIN anpr_1 y ON y.plate = x.plate
        AND ((date(y.timestamp) < date(x.timestamp))
        OR (date(y.timestamp) = date(x.timestamp)
        AND time(y.timestamp) <= time(x.timestamp)))
    GROUP BY x.plate , date(x.timestamp) , time(x.timestamp)) a
        JOIN
    (SELECT 
        x.plate,
            date(x.timestamp) as 'Date',
            time(x.timestamp) as 'time',
            COUNT(*) rank
    FROM
        anpr_2 x
    JOIN anpr_2 y ON y.plate = x.plate
        AND ((date(y.timestamp) < date(x.timestamp))
        OR (date(y.timestamp) = date(x.timestamp)
        AND time(y.timestamp) <= time(x.timestamp)))
    GROUP BY x.plate , date(x.timestamp) , time(x.timestamp)) b ON b.plate = a.plate AND b.rank = a.rank
where
    b.time > a.time
        and a.date = '2014-06-18'
        and b.date = '2014-06-18'
        and timediff(B.time, A.time) <= '03:00:00'
order by a.time;

虽然可能过于复杂,但此命令可以很好地满足我的需要。 但是,我现在要做的是创建另一个查询,将这些结果汇总到 15 分钟的时间段中,其中包含中值平均值、最小和最大旅程时间以及计数。因此,例如,上面显示的 15 分钟数据将显示为:

Timeslot    Median       Min           Max    Count
10:00:00    00:02:50    00:00:36    01:48:51    25
10:15:00    ??:??:??    ??:??:??    ??:??:??    ??

我尝试了group byUNIX_TIMESTAMPs 的各种组合,并查看了发布到此站点的类似问题,但我还没有在我想要实现的目标上取得多大成功。您有什么可以提供帮助的建议吗?

【问题讨论】:

  • 您真的想要结果的第二行,而不仅仅是实际存在数据的 15 分钟间隔的结果吗?
  • 作为示例的数据只是 15 分钟的一部分,整个数据集实际上是一个完整的 24 小时周期,我只是在问题中省略了它以保持简短和重点。如果需要,我可以提供一整天的示例数据。通常每 15 分钟的时间间隔内至少有一个数据条目。
  • 不,样本数据应该足够了。查询的最大问题是中位数,因为 MySQL 没有这样的功能。

标签: mysql sql median group-by


【解决方案1】:

这是一个平均行程时间而不是中位数的解决方案:

 SELECT
      `Date`,
      FLOOR(
      ((60* 60 * HOUR(TIMEDIFF(Starttime, '10:00:00')))
      + (60 * MINUTE(TIMEDIFF(Starttime, '10:00:00')))
      + SECOND(TIMEDIFF(Starttime, '10:00:00')))/(15 * 60)) as intervalNo,
      min(Journey_Time), max(Journey_Time), 
      SEC_TO_TIME(AVG(TIME_TO_SEC(Journey_Time))) as avgTime, 
      count(*) as Journeys  
 FROM table
 GROUP BY 1,2

请注意,这是基于每天 10:00:00 计算的。只需将其更改为任何其他开始时间。您可以使用 MySQL ADDTIME() 函数从 intervalNo 计算实际时间间隔(请参阅here)。

EDID

找到一个包含 15 分钟时隙的精简版:

 SELECT
    `Date`,
    FLOOR(TIME_TO_SEC(TIMEDIFF(Starttime, '10:00:00'))/(15 * 60)) as intervalNo,
    SEC_TO_TIME(FLOOR(TIME_TO_SEC(TIMEDIFF(Starttime, '10:00:00'))/(15 * 60)) * 15 * 60) 
              as TimeInterval,

    min(Journey_Time), max(Journey_Time),
    SEC_TO_TIME(AVG(TIME_TO_SEC(Journey_Time))),
    count(*) as Journeys

FROM table
GROUP BY 1,2

【讨论】:

  • 谢谢!这是朝着正确方向迈出的一大步,而且大部分都是我正在寻找的。我已将“10:00:00”更改为“00:00:00”以提供似乎是一整天的数据,但我不太确定 ADDTIME() 应该去哪里提供时间间隔。此外,这可能是我的格式/数据类型错误,但平均计算返回了很多 NULL 值。
  • 您的 Journey_Time col 是什么数据类型?时间到了吗?
  • 好的,更新了我的回答中的 avg() 函数。 Here 是为什么 :-)
  • 完美!这就解决了一切。非常感谢!
猜你喜欢
  • 2018-12-05
  • 1970-01-01
  • 1970-01-01
  • 2019-12-24
  • 2012-11-18
  • 1970-01-01
  • 1970-01-01
  • 2012-04-06
  • 1970-01-01
相关资源
最近更新 更多