我正在尝试从 MySQL 的数据集中查找连续范围的数值。但是,应忽略小于 5 的范围内的“间隙”。下面是我当前的代码(在某种程度上可以正常工作),为了方便起见,分割成较小的部分。
dataset
包含“时间”和“数字”列(均为数字)。最终目标是获取与 number > 200 关联的所有“thetime”范围。
(1) 首先,我通过选择编号 <= 200 的每个“时间”来选择数据集中的“间隙”。
drop temporary table if exists tmp_gaps;
create temporary table tmp_gaps as
(select thetime
from `dataset`
where number <= 200);
(2) 根据 here 解释的方法,我将这些发现的差距划分为范围。
drop temporary table if exists tmp_gaps_withdelta;
create temporary table tmp_gaps_withdelta as
(select min(thetime) as start, max(thetime) as theend, max(thetime) - min(thetime) + 1 as delta
from (select thetime, @curRow := @curRow + 1 as row_number
from tmp_gaps v
join (select @curRow := 0) w) v
group by thetime - row_number);
(3) 现在,我尝试通过将原始 dataset
表与 tmp_gaps_withdelta
合并来过滤 <= 5 的间隙。如果 delta <= 5 或 delta 为 null(意味着 tmp_gaps_withdelta
中没有对应于 dataset
中原始“thetime”的条目),我认为“thetime”是范围,它在 db_tmp_ranges
中被接受。
drop temporary table if exists db_tmp_ranges;
create temporary table db_tmp_ranges as
(select
case
when gaps.delta is null
or gaps.delta <= 5 then edm.thetime
else null
end as thetime
from `dataset` edm
left join tmp_gaps_withdelta gaps on edm.thetime >= gaps.start
and edm.thetime < gaps.start + gaps.delta);
到目前为止,一切都按预期进行。我现在有一大组“时间”值,其中原始表中的“数字”> 200。数据可以分成范围,没有间隙 <= 5。当我从 db_tmp_ranges
中选择一些数据时>,我得到了我所期待的。
(4) 现在打算分区,同(2)一样。
select *
from
(select min(thetime) as start, max(thetime) as theend, max(thetime) - min(thetime) + 1 as delta
from (select thetime, @curRow := @curRow + 1 as row_number
from db_tmp_ranges p
join (select @curRow := 0) r
where thetime is not null) p
group by thetime - row_number) q
但是,这个查询的结果是绝对错误的。老实说,我不知道问题出在哪里,因为这种间隔分区的方式一直对我有用,直到现在。非常感谢任何帮助。
编辑:查询如何 react 的具体示例: db_tmp_ranges:
...
1393001313
1393001315
1393001316
...
1393001596
1393001597
1393001598
...
上次查询的结果:
...
1393001316 1393001319 4
1393001320 1393001591 272
1393001592 1393001595 4
1393001596 1393001881 286
...
如您所见,这些数字应该在 1 个区间内,而不是 4+。使用 SQL fiddle 后,查询本身似乎没有问题。
我真的不明白。执行时...
select *
from db_tmp_ranges
where thetime >= 1393001313
and thetime <= 1393001350
order by thetime;
...我得到一个看起来很正常的数字“时间”值列表。但不知何故,最后一个查询没有按应有的方式使用 db_tmp_ranges。
最佳答案
MySQL 中最简单的方法是使用变量(在其他数据库中,您可以使用窗口/分析函数)。以下代码根据您的规则将 grp
列分配给数字:
select ds.*,
@grp := iff(@lastnumber - number <= 5, @grp, @grp + 1) as grp,
@lastnumber := number
from dataset ds cross join
(select @lastnumber := -1, @grp := 0) const
order by number;
获取实际序列:
select min(number), max(number), max(number) - min(number) as width,
count(distinct number) as numNumbers
from (select ds.*,
@grp := iff(@lastnumber - number <= 5, @grp, @grp + 1) as grp,
@lastnumber := number
from dataset ds cross join
(select @lastnumber := -1, @grp := 0) const
order by number
) ds
group by grp;
关于mysql - 搜索连续范围的数字,同时忽略 <= 5 的间隙,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23250784/