如何使用 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
我有一个数据库 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