SQL选择查询帮助。连续四行的最大总和。

时间:2013-10-21 23:27:27

标签: mysql sql

我们有一个交通计数器,以15分钟为增量对每个车道(两个入站和两个出站)的车辆进行计数。

有一个高峰期定义为上午7:00至9:00。在这个高峰期内,我们想知道 PeakHourIn PeakHourOut PeakHourSum

PeakHourIn 是lne1in + lne4in连续4x15分钟最长(1小时)

PeakHourOut 是lne2out + lne3out最高连续4x15分钟(1小时)

PeakHourSum 是所有泳道连续4x15分钟(1小时)的最高分。

Date    Time    lne1in  lne2out lne3out lne4in
09-18-2012  5:45 AM 2   0   0   0
09-18-2012  6:00 AM 1   0   0   1
09-18-2012  6:15 AM 2   1   0   0
09-18-2012  6:30 AM 2   1   0   0
09-18-2012  6:45 AM 6   1   2   1
09-18-2012  7:00 AM 9   1   0   3
09-18-2012  7:15 AM 81  12  22  15
09-18-2012  7:30 AM 144 31  63  56
09-18-2012  7:45 AM 84  30  62  42
09-18-2012  8:00 AM 7   1   0   3
09-18-2012  8:15 AM 11  2   3   3
09-18-2012  8:30 AM 12  3   7   1
09-18-2012  8:45 AM 16  4   8   0
09-18-2012  9:00 AM 5   2   5   0
09-18-2012  9:15 AM 10  1   4   0

结果应该如下:

PeakHourIn 434 PeakHourOut 221 PeakHourSum 655

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

如果您使用本机时态数据类型来存储日期/时间,则可以对多个自连接进行分组:

SELECT MAX(lne1in  + lne4in )                    AS PeakHourIn,
       MAX(lne2out + lne3out)                    AS PeakHourOut,
       MAX(lne1in  + lne2out + lne3out + lne4in) AS PeakHourSum
FROM   (
         SELECT t1.lne1in  + t2.lne1in  + t3.lne1in  + t4.lne1in  AS lne1in,
                t1.lne2out + t2.lne2out + t3.lne2out + t4.lne2out AS lne2out,
                t1.lne3out + t2.lne3out + t3.lne3out + t4.lne3out AS lne3out,
                t1.lne4in  + t2.lne4in  + t3.lne4in  + t4.lne4in  AS lne4in
         FROM   my_table t1
           JOIN my_table t2 ON t2.DateTime = t1.DateTime + INTERVAL 15 MINUTE
           JOIN my_table t3 ON t3.DateTime = t2.DateTime + INTERVAL 15 MINUTE
           JOIN my_table t4 ON t4.DateTime = t3.DateTime + INTERVAL 15 MINUTE
         WHERE    TIME(t1.DateTime) BETWEEN '07:00:00' AND '08:00:00'
         GROUP BY t1.DateTime
       ) t

答案 1 :(得分:0)

修改

以下是MySQL的解决方案:http://sqlfiddle.com/#!2/ff0fb/9

创建表TrafficData     (         StartTime时间戳
        ,Lane int         ,CarCount int     );

create table LaneData
(
    Lane int
    , Direction bit 
);

insert LaneData
      select 1, 0 
union select 2, 1 
union select 3, 1 
union select 4, 0;

insert TrafficData
select dt, lane
, case lane
    when 1 then l1
    when 2 then l2
    when 3 then l3
    when 4 then l4
    else null 
  end
from 
( 
    select '2012-09-18 05:45' dt, 2 l1, 0 l2, 0 l3, 0 l4
    union all select '2012-09-18 06:00', 1,   0,   0,   1
    union all select '2012-09-18 06:15', 2,   1,   0,   0
    union all select '2012-09-18 06:30', 2,   1,   0,   0
    union all select '2012-09-18 06:45', 6,   1,   2,   1
    union all select '2012-09-18 07:00', 9,   1,   0,   3
    union all select '2012-09-18 07:15', 81,  12,  22,  15
    union all select '2012-09-18 07:30', 144, 31,  63,  56
    union all select '2012-09-18 07:45', 84,  30,  62,  42
    union all select '2012-09-18 08:00', 7,   1,   0,   3
    union all select '2012-09-18 08:15', 11,  2,   3,   3
    union all select '2012-09-18 08:30', 12,  3,   7,   1
    union all select '2012-09-18 08:45', 16,  4,   8,   0
    union all select '2012-09-18 09:00', 5,   2,   5,   0
    union all select '2012-09-18 09:15', 10,  1,   4,   0
) as originalTable
cross join LaneData;

select Lane, max(SumCarCount) as MaxSumCarCount
from
(
    select a.Lane, SUM(b.CarCount) as SumCarCount
    from TrafficData a
    inner join TrafficData b
        on b.Lane = a.Lane
        and b.StartTime between a.StartTime and DATE_ADD(DATE_ADD(a.starttime, interval 1 hour), interval -1 second)
    where time(a.StartTime)  between '07:00' and '08:15' 
    group by a.Lane, a.StartTime
) x
group by Lane
order by Lane;

select Direction, max(SumCarCount) as MaxSumCarCount
from
(
    select al.Direction, SUM(b.CarCount) SumCarCount
    from TrafficData a
    inner join LaneData al
        on al.Lane = a.Lane
    inner join TrafficData b
        on b.StartTime between a.StartTime and DATE_ADD(DATE_ADD(a.starttime, interval 1 hour), interval -1 second)
    inner join LaneData bl
        on bl.Lane = b.Lane
        and bl.Direction = al.Direction
    where time(a.StartTime)  between '07:00' and '08:15' 
    group by al.Direction, a.StartTime
) x
group by Direction
order by Direction;

<强> ORIGINAL

以下是我在SQL Server中的用法:

--I'd change your table structure to be like this - that way you can easily add new lanes without rewriting the whole system
declare @trafficData table 
(
    StartTime   DateTime        
    ,Lane       int
    ,CarCount   int
)
--here's where you store additional info about the lanes (e.g. what direction they go in)
declare @laneData table
(
    Lane int
    , Direction bit --0 in, 1 out
)
--populate the tables with sample data
insert @laneData
      select 1, 0 
union select 2, 1 
union select 3, 1 
union select 4, 0

insert @trafficData
select dt, lane
, case lane
    when 1 then l1
    when 2 then l2
    when 3 then l3
    when 4 then l4
    else null --should never happen
  end
from 
( 
    select '2012-09-18 5:45 AM' dt, 2 l1, 0 l2, 0 l3, 0 l4
    union all select '2012-09-18 6:00 AM', 1,   0,   0,   1
    union all select '2012-09-18 6:15 AM', 2,   1,   0,   0
    union all select '2012-09-18 6:30 AM', 2,   1,   0,   0
    union all select '2012-09-18 6:45 AM', 6,   1,   2,   1
    union all select '2012-09-18 7:00 AM', 9,   1,   0,   3
    union all select '2012-09-18 7:15 AM', 81,  12,  22,  15
    union all select '2012-09-18 7:30 AM', 144, 31,  63,  56
    union all select '2012-09-18 7:45 AM', 84,  30,  62,  42
    union all select '2012-09-18 8:00 AM', 7,   1,   0,   3
    union all select '2012-09-18 8:15 AM', 11,  2,   3,   3
    union all select '2012-09-18 8:30 AM', 12,  3,   7,   1
    union all select '2012-09-18 8:45 AM', 16,  4,   8,   0
    union all select '2012-09-18 9:00 AM', 5,   2,   5,   0
    union all select '2012-09-18 9:15 AM', 10,  1,   4,   0
) originalTable
cross join @laneData

--peak for each individual lane
select * 
from
(
    select a.Lane, a.StartTime, SUM(b.CarCount) SumCarCount
    , ROW_NUMBER() over (partition by a.lane order by SUM(b.CarCount) desc) r
    from @trafficData a
    inner join @trafficData b
        on b.Lane = a.Lane
        and b.StartTime between a.StartTime and DATEADD(second,-1,DATEADD(hour,1,a.starttime))
    group by a.Lane, a.StartTime
) x
where r = 1
order by Lane 

--peak for lane direction
select *
from
(
    select al.Direction, a.StartTime, SUM(b.CarCount) SumCarCount
    , ROW_NUMBER() over (partition by al.Direction order by SUM(b.CarCount) desc) r
    from @trafficData a
    inner join @laneData al
        on al.Lane = a.Lane
    inner join @trafficData b
        on b.StartTime between a.StartTime and DATEADD(second,-1,DATEADD(hour,1,a.starttime))
    inner join @laneData bl
        on bl.Lane = b.Lane
        and bl.Direction = al.Direction
    group by al.Direction, a.StartTime
) x
where r = 1
order by Direction