比较具有相同ID的行的日期时间,仅返回日期时间差小于4小时的列

时间:2015-02-07 23:38:07

标签: mysql sql time-series

我真的在努力解决这个问题。任何帮助将不胜感激!

表格:

+------+----------+--------------------+--------+-------------------+
|Ref   |Dept      |DeptTime            |Arr     |ArrTime            |
+------+----------+--------------------+--------+-------------------+
|1     |New York  |2015-02-01 08:00:00 |Boston  |2015-02-01 09:00:00|
|1     |Boston    |2015-02-01 10:00:00 |Chicago |2015-02-01 11:00:00|
|1     |Chicago   |2015-02-01 12:00:00 |Dallas  |2015-02-01 13:00:00|
|1     |Dallas    |2015-02-02 11:00:00 |Seattle |2015-02-02 13:00:00|
|2     |London    |2015-02-01 04:00:00 |Berlin  |2015-02-01 16:00:00|
|2     |Berlin    |2015-02-02 18:00:00 |Moscow  |2015-02-02 23:00:00|
+------+----------+--------------------+--------+-------------------+

此表显示了多站jouneys。当到达和离开之间的停留时间少于4小时时,这应被视为同一行程的一部分。目的地应该是下次出发时间超过四小时的首次到达时间。在这种情况下,我想显示出发城市和出发时间,以及最终到达目的地和到达时间。您可以在此问题的底部看到所需的输出示例。

我认为查询应该做的是选择具有相同ref的值(使用join?),仅比较不同行的ArrTime和DeptTime,如果差异大于4小时,则返回Dept,DeptTime, Arr和ArrTime的多站旅程。超过4小时的任何事情都被视为该旅程的终点​​。

我尝试过使用几个简单的查询,但是我不知道如何计算具有相同Ref的不同项之间的Datetime差异,以及如何比较不同行之间的ArrTime和DeptTime。

我在StackOverflow上比较日期时发现了这个方法,但是我得到的只是在使用它时出现语法错误。

DECLARE @date1 DATETIME;
DECLARE @date2 DATETIME;

SET @date1 = '2012-04-01 08:10:16';
SET @date2 = '2012-04-10 11:35:36';

编辑:查询后的最终输出表应如下所示:

+------+----------+--------------------+--------+-------------------+
|Ref   |Dept      |DeptTime            |Arr     |ArrTime            |
+------+----------+--------------------+--------+-------------------+
|1     |New York  |2015-02-01 08:00:00 |Dallas  |2015-02-01 13:00:00|
|1     |Dallas    |2015-02-02 11:00:00 |Seattle |2015-02-02 13:00:00|
|2     |London    |2015-02-01 04:00:00 |Berlin  |2015-02-01 16:00:00|
|2     |Berlin    |2015-02-02 18:00:00 |Moscow  |2015-02-02 23:00:00|
+------+----------+--------------------+--------+-------------------+

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

我会通过创建两个中间表来进行报告。

第一个称为flight_journey。它根据您的时间要求将每个航班的航班分组。

第二个叫first_last。它标识了每个旅程中的第一个和最后一个航班,因为您想要展示它。

最终的select语句只使用带有自联接的first_last表来显示你想要的内容。

您可以索引中间表以提高性能。

FLIGHT_JOURNEY表:

create table flight_journey as
select z.*, @row_num := if(@prev_value=chk,@row_num+1,1) as journey
from(
select
   f.*, p.arrtime as prev_arr,
   case
when p.depttime is null then 1
when ifnull(hour(timediff(f.depttime, p.arrtime)), 0) <= 4 then
   1
else
   0
end as chk
from
   flights f
left join flights p on f.ref = p.ref
and p.depttime = (select max(z.depttime) from flights z where z.ref = p.ref and z.depttime < f.depttime)
) z,
 (select @row_num := 1) x,
      (select @prev_value := '') y
order by
   z.ref,
   z.depttime;

FIRST_LAST表:

create table first_last as
select
   y.*
from
   (select ref, journey, min(depttime) as min_dept, max(arrtime) as max_arr from flight_journey group by ref, journey) x
join flight_journey y on x.ref = y.ref
and x.journey = y.journey
and (x.min_dept = y.depttime or x.max_arr = y.arrtime);

最终选择声明:

select
   x.ref,
   x.dept,
   x.depttime,
   y.arr,
   y.arrtime
from
   first_last x
join first_last y on x.ref = y.ref
and x.journey = y.journey
and y.depttime > x.depttime
union all
   select
      x.ref,
      x.dept,
      x.depttime,
      x.arr,
      x.arrtime
   from
      first_last x
   join (select ref, journey from first_last group by ref, journey having count(*) = 1) y on x.ref = y.ref
   and x.journey = y.journey;

小提琴: http://sqlfiddle.com/#!2/f22b9/2/0

<强>输出:

| REF |     DEPT |                        DEPTTIME |     ARR |                         ARRTIME |
|-----|----------|---------------------------------|---------|---------------------------------|
|   1 | New York | February, 01 2015 08:00:00+0000 |  Dallas | February, 01 2015 13:00:00+0000 |
|   1 |   Dallas | February, 02 2015 11:00:00+0000 | Seattle | February, 02 2015 13:00:00+0000 |
|   2 |   London | February, 01 2015 04:00:00+0000 |  Berlin | February, 01 2015 16:00:00+0000 |
|   2 |   Berlin | February, 02 2015 18:00:00+0000 |  Moscow | February, 02 2015 23:00:00+0000 |
相关问题