sql - (SQL) 每个 ID,从第一行开始,返回值 N 大于前一个返回行的所有连续行
问题描述
我有以下示例数据集:
ID | 价值 | 行索引(仅供参考,最终输出中不需要存在) |
---|---|---|
一个 | 4 | 1 |
一个 | 7 | 2 |
一个 | 12 | 3 |
一个 | 12 | 4 |
一个 | 13 | 5 |
b | 1 | 6 |
b | 2 | 7 |
b | 3 | 8 |
b | 4 | 9 |
b | 5 | 10 |
我想编写一个 SQL 脚本,它返回下一行,其值为 N 或大于先前返回的行,从每个 ID 的第一行开始,并按 [Value] 升序排列。N = 3 的决赛桌示例应如下所示:
ID | 价值 | 行索引 |
---|---|---|
一个 | 4 | 1 |
一个 | 7 | 2 |
一个 | 12 | 3 |
b | 1 | 6 |
b | 4 | 9 |
这个脚本可以用矢量化的方式编写吗?还是必须使用循环?任何建议将不胜感激。谢谢!
解决方案
SQL 表表示无序集。没有“先前”值的定义,除非您有一个指定排序的列。使用这样的列,您可以使用lag()
:
select t.*
from (select t.*,
lag(value) over (partition by id order by <ordering column>) as prev_value
from t
) t
where prev_value is null or prev_value <= value - 3;
编辑:
我想我误解了你想要做什么。您似乎想从每个 id 的第一行开始。然后获取值为 3 或更高的下一行。然后保持该值并获得下一个大于或等于 3 的值。等等。
您可以使用递归 CTE 在 SQL 中执行此操作:
with ts as (
select distinct t.id, t.value, dense_rank() over (partition by id order by value) as seqnum
from t
),
cte as (
select id, value, value as grp_value, 1 as within_seqnum, seqnum
from ts
where seqnum = 1
union all
select ts.id, ts.value,
(case when ts.value >= cte.grp_value + 3 then ts.value else cte.grp_value end),
(case when ts.value >= cte.grp_value + 3 then 1 else cte.within_seqnum + 1 end),
ts.seqnum
from cte join
ts
on ts.id = cte.id and ts.seqnum = cte.seqnum + 1
)
select *
from cte
where within_seqnum = 1
order by id, value;
这是一个 db<>fiddle。
推荐阅读
- r - group_by() 和 summarise() 计算 sd 但返回 NA 作为平均值
- javascript - 在鼠标点击的地方动态追加输入
- sql-server - 每个 ID 的 SQL Server 词频
- git - 如何在 Git snapshpt 指针结构中表示多文件夹提交
- python - 如何使用框平均法对 netcdf 数据进行下采样
- html - 一个内部 div 在移动设备中分成 2 个未指定的列
- debugging - 隐藏numba编译的调试输出
- r - ggplot2:颜色特定的 ID 红色和其他以单独变量为条件的点
- javascript - 如何替换 contenteditable div 中的文本?
- windows - 在 Windows azure vm 启动时运行脚本