mysql - 搜索连续范围的数字,同时忽略 <= 5 的间隙

标签 mysql sql range partitioning

我正在尝试从 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/

相关文章:

Javascript - 日期范围验证

javascript - webkit (Safari/Chrome) 中的选择范围

mysql - 两个内部联接和第一个子句的 where

mysql - MySQL 中何时使用单引号、双引号和反引号

sql - 如何从 Oracle 表中获取几乎匹配的字符串?

c# - 如何实际执行命令?

php - 从 PDO 准备好的语句中获取 SQL 查询和参数

mysql - 在Windows上通过Bash使用MySQL

mysql - SQL 仅选择列上具有最大值的行

Python - 按字母顺序排列单词