获取表列中序列值的范围

问题描述

我的栏中有一个价值清单。并要查询范围。 例如。如果值为1,2,3,4,5,9,11,12,13,14,17,18,19

我想展示 1-5,11-14,17-19

解决方法

假设每个值都存储在单独的行中,则可以在此处使用一些空缺的技巧:

select case when min(val) <> max(val)
    then concat(min(val),'-',max(val))
    else min(val)
end val_range
from (select val,row_number() over(order by val) rn from mytable) t
group by val - rn
order by min(val)

这个想法是通过取值与递增等级之间的差来构建连续值的组,该等级使用row_number()(在MySQL 8.0中可用)计算:

Demo on DB Fiddle

| val_range |
| :-------- |
| 1-5       |
| 9         |
| 11-14     |
| 17-19     |

在早期版本中,您可以使用相关子查询或用户变量来模拟row_number()。第二个选项如下:

select case when min(val) <> max(val)
    then concat(min(val),max(val))
    else min(val)
end val_range
from (select @rn := 0) x
cross join (
    select val,@rn := @rn + 1 rn 
    from (select val from mytable order by val) t
) t
group by val - rn
order by min(val)
,

作为其他答案的补充:

select dn.val as dnval,min(up.val) as upval 
from mytable up
join mytable dn
    on dn.val <= up.val
where not exists (select 1 from mytable a where a.val = up.val + 1)
  and not exists (select 1 from mytable b where b.val = dn.val - 1)
group by dn.val
order by dn.val;

1   5
9   9
11  14
17  19

不用说,但是像@GNB一样使用OLAP函数,效率要高几个数量级。

有关如何在MySQL

mysql-row_number

Fiddle

编辑:

如果引入了另一个维度(在本例中为p),则类似:

select dn.p,dn.val as dnval,min(up.val) as upval 
from mytable up
join mytable dn
    on dn.val <= up.val
    and dn.p = up.p
where not exists (select 1 from mytable a where a.val = up.val + 1 and a.p = up.p)
  and not exists (select 1 from mytable b where b.val = dn.val - 1 and b.p = dn.p)
group by dn.p,dn.val
order by dn.p,dn.val;

可以使用,请参见Fiddle2

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...