获取表列中序列值的范围
Posted
技术标签:
【中文标题】获取表列中序列值的范围【英文标题】:get the range of sequence values in table column 【发布时间】:2020-08-28 12:39:53 【问题描述】:我的专栏中有一个价值列表。并想查询范围。 例如。如果值为 1,2,3,4,5,9,11,12,13,14,17,18,19
我想显示 1-5,9,11-14,17-19
【问题讨论】:
您实际上是在列中存储以逗号分隔的值列表,还是它们属于不同的行? 【参考方案1】:假设每个值都存储在单独的行中,您可以在此处使用一些间隙和孤岛技术:
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)
【讨论】:
当我尝试您的查询时,我收到了 val_range 的错误。我正在使用 mysql 5.7.19 @Zen:正如我提到的,这个解决方案需要 MySQL 8.0。我用早期版本的替代方法更新了我的答案。 @GMB 我花了一段时间来学习rn - val
查找群组的技巧。挺好用的。
@Zen。 . .我很惊讶 rn
在 5.17.19 工作的任务。我认为在那个版本中,您应该对order by
使用子查询,这恰好可以工作,因为该表是“按顺序”读取的。
@GordonLinoff:当涉及单个表时,我总是不确定我们是否需要在使用变量之前进行预购。你有指定的文档吗?【参考方案2】:
作为其他答案的补充:
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
【讨论】:
听起来很整洁,但我不能说它适用于我的海量数据。如果我想添加另一个过滤列怎么办。 不确定您所说的另一个过滤列是什么意思,您是指用作数字序列分区的列吗? @Zen,我已经扩展了示例,请参阅编辑。数据集越大,传统 SQL92 解决方案的成本就越高。如您所见,mytable 在查询中被引用了 4 次,而这只是row_number() over(partition by p order by val)
in GMB:s 问题的问题。
我试图提出一个一般性问题,也许我应该具体一点。我使用pos机打印卡片。表 sales 有 serial_no、pos_machine_no 和 card_amount 的列表。我想获取按 card_amount 分组的特定 pos 机器出售的 serial_no 的范围。
再问一个问题。确保包括带有说明问题的示例数据的 create table 语句和 insert 语句。 Dbfiddle 是 tvat 的绝佳工具以上是关于获取表列中序列值的范围的主要内容,如果未能解决你的问题,请参考以下文章