MySql select 相对相似的日期
MySql select relative similar dates
我试图 select 来自 table 的记录同时 window,例如
record_date | record_data
4/20/2015 5:00:00 PM | 23
4/20/2015 5:08:00 PM | 3
4/20/2015 5:09:00 PM | 98
如果我设置 2 分钟 window 将导致:
4/20/2015 5:08:00 PM | 3
4/20/2015 5:09:00 PM | 98
但是,如果我选择 15 分钟 window 必须得到:
4/20/2015 5:00:00 PM | 23
4/20/2015 5:08:00 PM | 3
4/20/2015 5:09:00 PM | 98
如何做到这一点? BETWEEN 或 DATEDIFF 语句需要一个绝对日期来比较,在这种情况下,比较必须与其他记录值相关,而不是与外部时间相关。
Mysql 不太擅长这个(这意味着 - 没有内置的东西)。
我们需要做的是根据 record_date
顺序为每一行关联一个等级。即,第一行的排名为 1,按日期紧邻的下一行的排名为 2,依此类推。
如果我们这样做,我们就可以很容易地将一行与下一行进行比较(即将 rank
与 rank + 1
进行比较)
这将为我们提供行对,以及按日期排列的紧接的下一行,然后我们可以过滤那些由您选择的 window 分隔的行。
为了将该结果转换为双列结果,我们需要重复查询,union
将结果放在一起,获取第一个查询中的第一个日期和数据,第二个日期和第二个查询中的数据。
union
默认为 distinct
,因此我们不会得到任何重复的行。这给了我们以下查询:
select * from (
select t1.record_date, t1.record_data from
(select @rank := @rank + 1 as rank, records.*
from records, (select @rank := 0) q order by record_date asc) t1
left join
(select @rank2 := @rank2 + 1 as rank, records.*
from records, (select @rank2 := 0) q order by record_date asc) t2
on t1.rank + 1 = t2.rank
where t2.record_date < t1.record_date + interval 2 minute
union
select t2.record_date, t2.record_data from
(select @rank := @rank + 1 as rank, records.*
from records, (select @rank := 0) q order by record_date asc) t1
left join
(select @rank2 := @rank2 + 1 as rank, records.*
from records, (select @rank2 := 0) q order by record_date asc) t2
on t1.rank + 1 = t2.rank
where t2.record_date < t1.record_date + interval 2 minute
) q
order by record_date asc;
或者,您可以像这样以稍微不那么夸张的方式进行操作:
select *
from (
select r1.record_date, r1.record_data
from records r1
inner join records r2
on r2.record_date = (select min(record_date) from records where record_date > r1.record_date)
where r2.record_date < r1.record_date + interval 2 minute
union
select r2.record_date, r2.record_data
from records r1
inner join records r2
on r2.record_date = (select min(record_date) from records where record_date > r1.record_date)
where r2.record_date < r1.record_date + interval 2 minute
) q
order by record_date asc;
我们不考虑排名,只是通过找到它的子查询直接加入下一个顺序日期。
我试图 select 来自 table 的记录同时 window,例如
record_date | record_data
4/20/2015 5:00:00 PM | 23
4/20/2015 5:08:00 PM | 3
4/20/2015 5:09:00 PM | 98
如果我设置 2 分钟 window 将导致:
4/20/2015 5:08:00 PM | 3
4/20/2015 5:09:00 PM | 98
但是,如果我选择 15 分钟 window 必须得到:
4/20/2015 5:00:00 PM | 23
4/20/2015 5:08:00 PM | 3
4/20/2015 5:09:00 PM | 98
如何做到这一点? BETWEEN 或 DATEDIFF 语句需要一个绝对日期来比较,在这种情况下,比较必须与其他记录值相关,而不是与外部时间相关。
Mysql 不太擅长这个(这意味着 - 没有内置的东西)。
我们需要做的是根据 record_date
顺序为每一行关联一个等级。即,第一行的排名为 1,按日期紧邻的下一行的排名为 2,依此类推。
如果我们这样做,我们就可以很容易地将一行与下一行进行比较(即将 rank
与 rank + 1
进行比较)
这将为我们提供行对,以及按日期排列的紧接的下一行,然后我们可以过滤那些由您选择的 window 分隔的行。
为了将该结果转换为双列结果,我们需要重复查询,union
将结果放在一起,获取第一个查询中的第一个日期和数据,第二个日期和第二个查询中的数据。
union
默认为 distinct
,因此我们不会得到任何重复的行。这给了我们以下查询:
select * from (
select t1.record_date, t1.record_data from
(select @rank := @rank + 1 as rank, records.*
from records, (select @rank := 0) q order by record_date asc) t1
left join
(select @rank2 := @rank2 + 1 as rank, records.*
from records, (select @rank2 := 0) q order by record_date asc) t2
on t1.rank + 1 = t2.rank
where t2.record_date < t1.record_date + interval 2 minute
union
select t2.record_date, t2.record_data from
(select @rank := @rank + 1 as rank, records.*
from records, (select @rank := 0) q order by record_date asc) t1
left join
(select @rank2 := @rank2 + 1 as rank, records.*
from records, (select @rank2 := 0) q order by record_date asc) t2
on t1.rank + 1 = t2.rank
where t2.record_date < t1.record_date + interval 2 minute
) q
order by record_date asc;
或者,您可以像这样以稍微不那么夸张的方式进行操作:
select *
from (
select r1.record_date, r1.record_data
from records r1
inner join records r2
on r2.record_date = (select min(record_date) from records where record_date > r1.record_date)
where r2.record_date < r1.record_date + interval 2 minute
union
select r2.record_date, r2.record_data
from records r1
inner join records r2
on r2.record_date = (select min(record_date) from records where record_date > r1.record_date)
where r2.record_date < r1.record_date + interval 2 minute
) q
order by record_date asc;
我们不考虑排名,只是通过找到它的子查询直接加入下一个顺序日期。