如何使用 PLSQL 根据一列中的重复值和另一列中的连续值进行过滤?

How to filter based on duplicate values in one column and consecutive values in another using PLSQL?

我有一个数据库 table,其中一个特定列中包含一些重复行。我只想显示那些行,但仅当相邻列对每组匹配的重复项都有连续数字时才显示。下图演示:

这是我到目前为止的想法(下面的列名与上面的图片不同,这样做是为了避免与定义的 SQL 函数发生冲突):

SELECT BIZ_DATE, AMT, COUNT(*) FROM MY_TABLE WHERE TRAN_DATE 
= '03-APR-2000' GROUP BY  AMT, BIZ_DATE, AMT HAVING COUNT(*) > 1; 

这对于在 amt 列中获取欺骗似乎相当有效。

现在,如何让它只考虑 trans_id 列中的连续值?

取决于如何你想恢复你的"duplicate"行,类似的东西可能会起作用:

DECLARE
  CURSOR c IS SELECT * FROM T ORDER BY AMT,NAME,TRANS_ID;
  curr_rec c%ROWTYPE;
  base_rec c%ROWTYPE;
BEGIN
  FOR curr_rec IN c
  LOOP
    IF curr_rec.AMT = base_rec.AMT AND curr_rec.NAME = base_rec.NAME
    THEN
        DBMS_OUTPUT.PUT(base_rec.TRANS_ID);
        DBMS_OUTPUT.PUT(' ');
        DBMS_OUTPUT.PUT_LINE(curr_rec.TRANS_ID);
    ELSE
        base_rec := curr_rec;
    END IF;
  END LOOP;
NULL;
END;

这是对已排序行的简单循环,以根据条件 curr_rec.AMT = base_rec.AMT AND curr_rec.NAME = base_rec.NAME(或您需要的任何其他条件,只要它匹配 前缀 光标的 SORTED 子句)

根据您的示例数据,输出为:

8085 8086
8085 8087
8085 8088

PL/SQL 并非严格要求查找共享一个属性但在另一个属性上具有连续值的数据。

使用您的一般 table 结构,以下将定位任何共享相同 BIZ_DATE 和 AMT 的交易对,以及相邻的 TRANS_IDs.

创建并加载 table 后:

    CREATE TABLE MY_TABLE    (
    BIZ_DATE DATE          NOT NULL,
    NAME     VARCHAR2(200) NOT NULL,
    AMT      NUMBER        NOT NULL,
    TRANS_ID NUMBER        NOT NULL    );

    INSERT INTO MY_TABLE
    (BIZ_DATE, NAME, TRANS_ID, AMT)
    VALUES (TO_DATE('17-MAY-2015', 'DD-MON-YYYY'), 'BOB', 8086, 159);

    INSERT INTO MY_TABLE
    (BIZ_DATE, NAME, TRANS_ID, AMT)
    VALUES (TO_DATE('17-MAY-2015', 'DD-MON-YYYY'), 'BOB', 8085, 159);

    INSERT INTO MY_TABLE
    (BIZ_DATE, NAME, TRANS_ID, AMT)
    VALUES (TO_DATE('17-MAY-2015', 'DD-MON-YYYY'), 'BOB', 9088, 159);

    INSERT INTO MY_TABLE
    (BIZ_DATE, NAME, TRANS_ID, AMT)
    VALUES (TO_DATE('17-MAY-2015', 'DD-MON-YYYY'), 'BOB', 9087, 159);

    INSERT INTO MY_TABLE
    (BIZ_DATE, NAME, TRANS_ID, AMT)
    VALUES (TO_DATE('17-MAY-2015', 'DD-MON-YYYY'), 'BOB', 1111, 159);

    INSERT INTO MY_TABLE
    (BIZ_DATE, NAME, TRANS_ID, AMT)
    VALUES (TO_DATE('17-APR-2015', 'DD-MON-YYYY'),'BOB', 5903, 159);

    INSERT INTO MY_TABLE
    (BIZ_DATE,NAME, TRANS_ID, AMT)
    VALUES (TO_DATE('17-MAR-2015', 'DD-MON-YYYY'),'BOB', 5904, 160);

可以通过解析函数比较相邻值:

SELECT
  BIZ_DATE,
  AMT,
  TRANS_ID,
  PRIOR_TRANS_ID
FROM
  (SELECT
     BIZ_DATE,
     AMT,
     TRANS_ID,
     LAG(TRANS_ID, 1, TRANS_ID)
     OVER (PARTITION BY BIZ_DATE, AMT
       ORDER BY TRANS_ID ASC)
       AS PRIOR_TRANS_ID
   FROM MY_TABLE
   WHERE BIZ_DATE = TO_DATE('17-MAY-2015', 'DD-MON-YYYY'))
WHERE (TRANS_ID - PRIOR_TRANS_ID) = 1;

结果:

BIZ_DATE   AMT TRANS_ID PRIOR_TRANS_ID
2015-05-17  159 8086    8085
2015-05-17  159 9088    9087