我有一个访问表(id int,start datetime,end datetime),我希望跟踪峰值访问次数。
示例数据:
+------+---------------------+---------------------+
| id | date-time-1 | date-time-2 |
+------+---------------------+---------------------+
| 1059 | 2016-07-04 19:13:00 | 2016-07-04 19:20:05 |
| 1060 | 2016-07-04 19:13:30 | 2016-07-04 19:14:25 |
| 1061 | 2016-07-04 19:14:39 | 2016-07-04 19:20:05 |
| 1062 | 2016-07-05 02:34:40 | 2016-07-05 02:45:23 |
| 1063 | 2016-07-05 02:34:49 | 2016-07-05 02:45:34 |
+------+---------------------+---------------------+
预期结果应为:
+-------------------------------------------+-------+
| date-time-1 | date-time-2 | count |
+-------------------------------------------+-------+
| 2016-07-04 19:13:00 | 2016-07-04 19:13:29 | 1 |
| 2016-07-04 19:13:30 | 2016-07-04 19:14:25 | 2 |
| 2016-07-04 19:14:26 | 2016-07-04 19:14:38 | 1 |
| 2016-07-04 19:14:39 | 2016-07-04 19:20:05 | 2 |
| 2016-07-04 19:20:06 | 2016-07-05 02:34:39 | 0 |
| 2016-07-05 02:34:40 | 2016-07-05 02:34:48 | 1 |
| 2016-07-05 02:34:49 | 2016-07-05 02:45:23 | 2 |
| 2016-07-05 02:45:24 | 2016-07-05 02:45:34 | 1 |
+------+------------------------------------+-------+
答案 0 :(得分:0)
这不是很有效,但它会给你你的结果:
select U.dt1 as date-time-1, DATE_ADD(U.dt2,INTERVAL -1 SECOND) as date-time-2,
(select count(id) from Visits where
(dt1 >= u.dt1 and dt1<U.dt2) --(dt1)dt2
or (dt1<u.dt1 and dt2>=u.dt2) -- dt1()dt2
--or (dt2 >= u.dt1 and dt2<U.dt2) -- dt1(dt2) (comment this line to get your result which I believe is incorrect)
) as count
from (
select A.dt1 as dt1, (
select min(M.dt) from ( select min(dt2) as dt from Visits where dt2 > A.dt1 union select min(dt1) as dt from Visits where dt1 > A.dt1) M
) as dt2 from Visits A
union
select B.dt2 as dt1, (
select min(M.dt) from ( select min(dt2) as dt from Visits where dt2 > b.dt2 union select min(dt1) as dt from Visits where dt1 > b.dt2) M
) as dt2 from Visits b where B.dt2 <> (select max(dt2) from Visits)
) U
我已经评论了条件检查以查看访问是否在范围之前开始并在其中结束以获得与您相同的结果集,但我相信您应该考虑这一点。
答案 1 :(得分:0)
因此,为了完成这项工作,您需要了解您的期间和之间的重叠。我们在评论中同意,为了让它以正确的方式工作,你应该从第二行开始,至少有一秒加到前一端。为了理解我将添加一个图表,显示您的期间将如何以及正好在package -> socket.io-client
表格的时间段之后,这样您最终会看到时间(因为所有期间都是同一天和小时,我将在图表上留下几分钟和几秒钟)
visits
为了实现这样的时间段,我创建了一个13:00 13:30 14:26 14:39
^ ^ ^ ^
|------------||-----------||----------||-----------|
|_ 13:31 |_ 14:25 |_ 14:40 |_ 20:05
--and in your table
13:00 20:05
^ ^
|--------------------------------------------------|
|------------| 14:39 20:05
|_ 13:30 |_ 14:25 ^ ^
|------------|
以方便查询,这里是代码:
VIEW
此观点的目的是确定您所定期间的所有日期create or replace view vw_times as
select dtstart as dt from visits
UNION
select dtend as dt from visits;
和starts
。
以下是将产生此类时间段的查询:
ends
从中你可以SELECT case when cnt>1
then date_add(dtstart,interval 1 second)
else dtstart
end as dtstart,
dtend
from (SELECT dtstart,
dtend,
@ct:=@ct+1 as cnt
FROM ( SELECT t1.dt as dtstart,
(select min(x.dt)
from vw_times as x
where x.dt > t1.dt
) as dtend
FROM vw_times t1,
(select @ct := 0) as cttab
ORDER BY t1.dt
) t2
WHERE dtend is not null
) as t3
你的桌子找到这样的重叠时期:
LEFT JOIN
这将导致:
SELECT times.dtstart, times.dtend, count(*)
FROM (SELECT case when cnt>1
then date_add(dtstart,interval 1 second)
else dtstart
end as dtstart,
dtend
from (SELECT dtstart,
dtend,
@ct:=@ct+1 as cnt
FROM ( SELECT t1.dt as dtstart,
(select min(x.dt)
from vw_times as x
where x.dt > t1.dt
) as dtend
FROM vw_times t1,
(select @ct := 0) as cttab
ORDER BY t1.dt
) t2
WHERE dtend is not null
) as t3
) as times
LEFT JOIN visits v
ON ( times.dtstart >= v.dtstart
AND times.dtend <= v.dtend)
GROUP BY times.dtstart, times.dtend
在此处查看:http://sqlfiddle.com/#!9/3509ff/10
修改强>
由于您添加了带有最终结果的注释,因此最终查询会更小:
dtstart dtend count(*)
July, 04 2016 19:13:00 July, 04 2016 19:13:30 1
July, 04 2016 19:13:31 July, 04 2016 19:14:25 2
July, 04 2016 19:14:26 July, 04 2016 19:14:39 1
July, 04 2016 19:14:40 July, 04 2016 19:20:05 2
这将导致:
SELECT times.dtstart,
case when times.dtend = vmax.maxend
then date_add(times.dtend, interval 1 second)
else times.dtend
end as dtend,
count(*)
FROM (SELECT dtstart,
dtend
FROM ( SELECT t1.dt as dtstart,
(select min(date_sub(x.dt, interval 1 second))
from vw_times as x
where x.dt > t1.dt
) as dtend
FROM vw_times t1
ORDER BY t1.dt
) t2
WHERE t2.dtend is not null
) as times
LEFT JOIN visits as v
ON ( times.dtstart >= v.dtstart
AND times.dtend <= v.dtend)
LEFT JOIN (select max(date_sub(v.dtend, interval 1 second)) as maxend
from visits v) vmax
ON ( times.dtend = vmax.maxend )
GROUP BY times.dtstart,
case when times.dtend = vmax.maxend
then date_add(times.dtend, interval 1 second)
else times.dtend
end