2015-06-14 65 views
1

我的目标是获取按id排序的一组数据,并返回指示val列相同的连续行数的结果集。例如。给定数据:用于运行长度或连续相同值编码的SQL查询

| id | val | 
| 1 | 33 | 
| 2 | 33 | 
| 3 | 44 | 
| 4 | 28 | 
| 5 | 44 | 
| 6 | 44 | 

我希望看到这样的结果:

| id | val | run_length | 
| 1 | 33 | 2   | 
| 3 | 44 | 1   | 
| 4 | 28 | 1   | 
| 5 | 44 | 2   | 

在结果中的id列是可选的。事实上,如果这会让问题变得更加困难,那么只需将该列留在结果中即可。我有点喜欢,因为它将结果集“钉”到表中的特定位置。

我主要对免费数据库引擎的结果感兴趣。我偏爱的解决方案的顺序是:

  1. SQLite的
  2. Postgres的
  3. MySQL的
  4. 甲骨文
  5. SQL服务器
  6. 的Sybase

回答

1

我会选择#2你的列表,因为这在SQLite中使用单个查询非常痛苦。以下是标准的SQL:

select min(id), val, count(*) as runlength 
from (select t.*, 
      (row_number() over (order by id) - 
       row_number() over (partition by val order by id 
      ) as grp 
     from data t 
    ) t 
group by grp, val; 

此使用两个行号计算的差来识别相同的值的seuqnces。它应该在最新版本的数据库2,4,5和6中工作。

-1

我一直在SQLITE中的RLE空间四处游荡,并跑过这篇文章。我相信这个代码适用于#1。第一个答案是正确的,这在SQLite中是一个单一的查询。

create table example (id integer primary key autoincrement, val integer); 

insert into example (val) values (33); 
insert into example (val) values (33); 
insert into example (val) values (44); 
insert into example (val) values (28); 
insert into example (val) values (44); 
insert into example (val) values (44); 


select ren.low_id, e2.val, (ren.high_id - ren.low_id)+1 
from example e2 
inner join (
select min(hb.low_id) as low_id, hb.high_id as high_id 
from 
(
    with nexample(low_id, high_id, val) 
    as 
    (
    select e.id, e.id, e.val from example e 
    union all 
    select ne.low_id, eu.id, ne.val 
    from nexample ne 
    inner join example eu on eu.id = ne.high_id+1 AND eu.val=ne.val 
    ) 
    select ne.low_id, max(ne.high_id) as high_id from nexample ne 
    group by ne.low_id 
) hb 
group by hb.high_id 
) ren on ren.low_id = e2.id; 

输出:

1|33|2 
3|44|1 
4|28|1 
5|44|2 

注意:此解决方案不上非常稀疏集表现良好......我在寻找一个替代的办法来处理稀疏套。

例如,在一组10000行中,val的值为[0,1],但所有值均为0.此代码需要大约2分30秒才能在我的硬件上运行。不是很好。