问题描述
我的栏中有一个价值清单。并要查询范围。 例如。如果值为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中可用)计算:
| 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
编辑:
如果引入了另一个维度(在本例中为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