从 SQL 到 SPL:获取搜索到的记录之后和之前的记录
mariadb 数据库某表的 ProductionLine_Number 是分类字段,组内的 Cardboard_Number 字段值有重复。
id |
Cardboard_Number |
date_Time |
ProductionLine_Number |
2 |
WDL-005943998-1 |
2024-02-29 17:13:50 |
1 |
4 |
spL1ml82N4o |
2024-02-29 17:13:54 |
1 |
5 |
WDL-005943998-1 |
2024-03-01 09:44:42 |
1 |
6 |
WDL-005943998-1 |
2024-03-01 10:34:57 |
1 |
7 |
950024027237 |
2024-03-01 10:44:57 |
1 |
8 |
950024027237 |
2024-03-01 10:52:57 |
1 |
9 |
WDL-005943998-1 |
2024-03-01 13:58:43 |
2 |
10 |
WDL-005943998-1 |
2024-03-01 13:58:46 |
2 |
11 |
spL1ml82N4o |
2024-03-01 14:09:43 |
2 |
12 |
WDL-005943998-1 |
2024-03-12 15:48:36 |
2 |
按 ProductionLine_Number 分组,组内按 date_Time 排序后,要从每组数据中搜索到 Cardboard_Number 等于指定字符串的所有记录,获取搜索到的记录的指定偏移量之前和之后的记录,并去除重复记录。比如 Cardboard_Number= "WDL-005943998-1",偏移量为 1,则结果如下:
id |
Cardboard_Number |
date_Time |
ProductionLine_Number |
2 |
WDL-005943998-1 |
2024-02-29 17:13:50 |
1 |
4 |
spL1ml82N4o |
2024-02-29 17:13:54 |
1 |
5 |
WDL-005943998-1 |
2024-03-01 09:44:42 |
1 |
6 |
WDL-005943998-1 |
2024-03-01 10:34:57 |
1 |
7 |
950024027237 |
2024-03-01 10:44:57 |
1 |
9 |
WDL-005943998-1 |
2024-03-01 13:58:43 |
2 |
10 |
WDL-005943998-1 |
2024-03-01 13:58:46 |
2 |
11 |
spL1ml82N4o |
2024-03-01 14:09:43 |
2 |
12 |
WDL-005943998-1 |
2024-03-12 15:48:36 |
2 |
如果 Cardboard_Number= "spL1ml82N4o",偏移量为 2,则结果的 ID=2,4,5,6,9,10,11,12
SQL:
with ranked_table AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ProductionLine_Number ORDER BY date_Time) AS rn
FROM table1
),
filtered_table AS (
SELECT id, Cardboard_Number, date_Time, ProductionLine_Number,rn
FROM ranked_table
WHERE Cardboard_Number = 'WDL-005943998-1'
)
SELECT DISTINCT t1.id, t1.Cardboard_Number, t1.date_Time, t1.ProductionLine_Number
FROM ranked_table t1
JOIN filtered_table t2
ON t1.ProductionLine_Number = t2.ProductionLine_Number
AND (t1.rn = t2.rn OR t1.rn = t2.rn - 1 OR t1.rn = t2.rn + 1)
ORDER BY ProductionLine_Number, date_Time;
SQL 要用窗口函数拼出序号,再用 JOIN 实现区间关联,代码比较冗长。SPL 有分组子集且有位置引用机制,代码简单:https://try.esproc.com/splx?3Io
A |
|
1 |
$select * from table1.txt order by ProductionLine_Number, date_Time |
2 |
=A1.group(ProductionLine_Number) |
3 |
=A2.conj(~.select(Cardboard_Number[-1:1].contain("WDL-005943998-1"))) |
A2:分组但不汇总。
A3:搜索各组子集的记录,找出前后各 1 条记录(共 3 条)的区间内,Cardboard_Number 字段等于指定字符串的记录,再合并各组计算结果。[-1:1] 表示相对区间范围。
英文版 https://c.esproc.com/article/1739958213554