Oracle - 沿间隔分组值
Posted
技术标签:
【中文标题】Oracle - 沿间隔分组值【英文标题】:Oracle - grouping values along interval 【发布时间】:2016-12-20 12:52:55 【问题描述】:我需要查询一个表,其中包含一个步骤 id + 值。 结果将列出间隔及其相关值。 这里的区间被定义为“步骤的连续 id 的连续,共享相同的数据值”。
我很难用语言来描述它,所以请看这个:
从这张表
Step ! Data
------------
1 ! A
2 ! A
3 ! A
5 ! A
6 ! B
10 ! A
我需要以下报告
From ! To ! Data
-------------------
1 ! 3 ! A
5 ! 5 ! A
6 ! null ! B
10 ! null ! A
我认为lead() 会在这里帮助我,但没有成功。
【问题讨论】:
似乎数据是针对值 A 和 B 分别考虑的?那么:为什么该行的结果是 (5, 5),然后是 (6, NULL) 而不是 (6, 6)? 哦...所以,对于每个“数据”值的最后一次出现,间隔应该是开放式的,但所有其他间隔都是“封闭式”的? 你说得对,这还是有点过度指定:“To”值显示为“From”而不是 NULL 是完全可以接受的 如果我们也有A ! 11
,您希望最后一个范围是 '10 吗?空`或`10! 11'?
【参考方案1】:
select min (step) as "from"
,nullif (max (step),max(min(step)) over (partition by data)) as "to"
,data
from (select step,data
,row_number () over (partition by data order by step) as n
from t
)
group by data
,step - n
order by "from"
【讨论】:
样本结果,不应该是5 ! null ! A
而不是5 ! 5 ! A
吗?
NULL 仅表示最后一个开放区间。正如你所看到的,对于值 A,一个新的间隔从第 10 步开始,这就是为什么从 5 开始的间隔也在那里结束。
请加'A! 11`到结果集,然后比较解决方案
非常感谢@Dudu Markovitz,您的解决方案完全满足了我最初的需求——空值确实为开放式区间带来了有用的信息。【参考方案2】:
您可以通过生成一个数字序列并从step
中减去来做到这一点。当值是连续的时,这将是一个常量:
select min(step) as from_step, max(step) as to_step, data
from (select t.*,
row_number() over (partition by data order by step) as seqnum
from t
) t
group by (step - seqnum), data;
编辑:
尚不清楚NULL
s 的来源。如果我推测它们是每个值的最后一个值,您可以这样做:
select min(step) as from_step,
(case when max(step) <> max_step then max(step) end) as to_step,
data
from (select t.*,
max(step) over (partition by data) as max_step
row_number() over (partition by data order by step) as seqnum
from t
) t
group by (step - seqnum), data, max_step;
【讨论】:
OP没有解释得很好,但是数据似乎是按值分区的(看步骤5-6)。 @mathguy 。 . .这就是这个解决方案的作用。 @GordonLinoff 不应该row_number
是 partition by data
或者至少在 order
克劳斯中使用 data
?
哇,这速度又快又高效
将data
放入row_number()
绝对是一种选择。在这种情况下不需要这样做,因为这些步骤似乎是一个单调递增的序列。以上是关于Oracle - 沿间隔分组值的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Oracle SQL 上进行查询以获取时间间隔,按特定字段分组