如何用SQL检查同类别排序行的金额依赖一致性?
一致性检查的SQL实现
需求说明:对于每个类别(Name列),按dt列排序后的行之间存在依赖关系:第i行的End_am必须等于第i+1行的Start_am。
示例数据表定义如下:
CREATE TABLE table_name (Name,dt,Start_am,End_am) AS SELECT 'A', DATE '2000-01-04', FLOAT 0, FLOAT 20 FROM DUAL UNION ALL SELECT 'A', DATE '2000-01-05', FLOAT 20, FLOAT 0 FROM DUAL UNION ALL SELECT 'A', DATE '2000-01-08', FLOAT 0, FLOAT 15 FROM DUAL UNION ALL SELECT 'A', DATE '2000-01-10', FLOAT 15, FLOAT 25 FROM DUAL UNION ALL SELECT 'A', DATE '2000-01-11', FLOAT 333, FLOAT 25 FROM DUAL UNION ALL SELECT 'A', DATE '2000-01-12', FLOAT 25, FLOAT 25 FROM DUAL UNION ALL SELECT 'B', DATE '2001-02-05', FLOAT 1, FLOAT 2 FROM DUAL UNION ALL SELECT 'B', DATE '2001-02-09', FLOAT 2, FLOAT 2 FROM DUAL UNION ALL SELECT 'B', DATE '2001-02-10', FLOAT 2, FLOAT 0 FROM DUAL UNION ALL SELECT 'B', DATE '2001-02-11', FLOAT 0, FLOAT 0 FROM DUAL UNION ALL SELECT 'B', DATE '2001-02-12', FLOAT 0, FLOAT -1 FROM DUAL UNION ALL SELECT 'B', DATE '2001-02-13', FLOAT -1, FLOAT 0 FROM DUAL UNION ALL SELECT 'B', DATE '2001-02-14', FLOAT 0, FLOAT 0 FROM DUAL;
示例中,Name为B的数据完全符合一致性要求,而Name为A的数据在
2000-01-11存在不匹配:当日Start_am为333,与前一日(2000-01-10)的End_am(25)不符。请问能否用SQL实现该一致性检查?
当然可以实现,核心就是用窗口函数LAG()获取每个Name分组内前一行的End_am,再和当前行的Start_am对比,筛出不匹配的记录。
实现SQL
SELECT Name, dt, Start_am, End_am, prev_end_am AS 前一日结束金额, '起始金额与前一日结束金额不匹配' AS 不一致原因 FROM ( SELECT t.*, LAG(End_am) OVER (PARTITION BY Name ORDER BY dt) AS prev_end_am FROM table_name t ) sub WHERE prev_end_am IS NOT NULL -- 跳过每个分组的第一行(没有前置记录,无需检查) AND Start_am != prev_end_am;
结果说明
跑这个SQL就能直接拿到所有不符合一致性要求的记录:
- 针对示例数据,会返回Name为A、日期是
2000-01-11的行,能清楚看到当前行的起始金额、前一行的结束金额,以及不一致的原因。
额外说明
LAG(End_am) OVER (PARTITION BY Name ORDER BY dt):按Name分组,每组内按日期升序排列,取当前行上一行的End_am值。- 加
prev_end_am IS NOT NULL是因为每个分组的第一行没有上一条记录,不需要做检查。 - 如果业务上还要验证第一行的起始金额是否合法,可根据需求修改过滤条件。
内容的提问来源于stack exchange,提问作者aeiou
相关产品推荐
相关产品推荐

