Oracle SQL 显示来自相同 table 的匹配数据

Oracle SQL showing matching data from same table

你好,我有关注table:

Id  Code  Acct
=================
1   002   123456
1   004   123456
2   004   456789
2   004   123456
3   001   3456456
4   005   975236
5   006   146387
6   004   0054321
6   010   123456
7   008   165432
7   007   987654
7   002   123456

我需要通过以下方式找到匹配 CodeAcct 的 ID:

Code Acct    Id1 Id2
=====================
002  123456  1   7
004  123456  1   2

Self-join(第 1 - 15 行代表示例数据;您需要的查询从第 16 行开始):

SQL> with test (id, code, acct) as
  2    (select
  3  1,   '002',   123456  from dual union all select
  4  1,   '004',   123456  from dual union all select
  5  2,   '004',   456789  from dual union all select
  6  2,   '004',   123456  from dual union all select
  7  3,   '001',   3456456 from dual union all select
  8  4,   '005',   975236  from dual union all select
  9  5,   '006',   146387  from dual union all select
 10  6,   '004',   0054321 from dual union all select
 11  6,   '010',   123456  from dual union all select
 12  7,   '008',   165432  from dual union all select
 13  7,   '007',   987654  from dual union all select
 14  7,   '002',   123456  from dual
 15  )
 16  select a.code, a.acct, a.id id1, b.id id2
 17  from test a join test b on a.code = b.code
 18                         and a.acct = b.acct
 19                         and a.id > b.id
 20  order by code, acct;

COD       ACCT        ID1        ID2
--- ---------- ---------- ----------
002     123456          7          1
004     123456          2          1

SQL>

如果您有任意数量的重复项(即可能超过 2 个),或者您希望单次通过 table,您可以使用一些解析 SQL

SQL> with t as
  2  (
  3  select 1 id,  002 code, 123456 acct from dual union all
  4  select 1,  004 , 123456 acct from dual union all
  5  select 2,  004 , 456789 acct from dual union all
  6  select 2,  004 , 123456 acct from dual union all
  7  select 3,  001 , 3456456 acct from dual union all
  8  select 4,  005 , 975236 acct from dual union all
  9  select 5,  006 , 146387 acct from dual union all
 10  select 6,  004 , 0054321 acct from dual union all
 11  select 6,  010 , 123456 acct from dual union all
 12  select 7,  008 , 165432 acct from dual union all
 13  select 7,  007 , 987654 acct from dual union all
 14  select 7,  002 , 123456 acct from dual
 15  ),
 16  dups as (
 17   select t.*,
 18      count(*) over ( partition by code,acct ) as dup_cnt
 19    from t
 20  )
 21  select code, acct, listagg(id,',') within group ( order by id) as id_list
 22  from dups
 23  where dup_cnt > 1
 24  group by  code, acct;

      CODE       ACCT ID_LIST
---------- ---------- ------------------------------
         2     123456 1,7
         4     123456 1,2

您可以先使用 LISTAGG 然后 REGEXP_SUBSTR

SELECT CODE,
       ACCT,
       REGEXP_SUBSTR (CONCT,
                      '[^,]+',
                      1,
                      1)
          ID1,
       REGEXP_SUBSTR (CONCT,
                      '[^,]+',
                      1,
                      2)
          AS ID2
  FROM (WITH MAIN
             AS (SELECT 1 AS ID, '002' AS CODE, '123456' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 1 AS ID, '004' AS CODE, '123456' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 2 AS ID, '004' AS CODE, '456789' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 2 AS ID, '004' AS CODE, '123456' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 3 AS ID, '001' AS CODE, '3456456' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 4 AS ID, '005' AS CODE, '975236' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 5 AS ID, '006' AS CODE, '146387' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 6 AS ID, '004' AS CODE, '0054321' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 6 AS ID, '010' AS CODE, '123456' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 7 AS ID, '008' AS CODE, '165432' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 7 AS ID, '007' AS CODE, '987654' AS ACCT FROM DUAL
                 UNION ALL
                 SELECT 7 AS ID, '002' AS CODE, '123456' AS ACCT FROM DUAL)
          SELECT A.CODE,
                 A.ACCT,
                 LISTAGG (A.ID, ',') WITHIN GROUP (ORDER BY A.ID) AS CONCT
            FROM MAIN A
        GROUP BY A.CODE, A.ACCT)

你可以试试这个。

SQLFiddle

WITH CTE1 AS (
SELECT * FROM TABLE1 WHERE (CODE, ACCT) IN (
SELECT CODE, ACCT FROM (
select count(1), CODE, ACCT FROM TABLE1
GROUP BY CODE, ACCT HAVING COUNT(1) > 1) T))
SELECT X.ID ID1, Y.ID ID2, X.CODE, X.ACCT FROM CTE1 X, CTE1 Y WHERE X.CODE = Y.CODE AND X.ACCT
= Y.ACCT AND X.ID > Y.ID;

只需使用聚合:

select code, account, min(id), max(id)
from t
group by code, account
having count(*) > 1;

注意:这只有 returns 两个匹配的示例 ID。如果你想要所有这些,你可以使用 listagg():

select code, account, listagg(id, ',') within group (order by id) as ids
from t
group by code, account
having count(*) > 1;