【问题标题】:How to find duplicate records in oracle CASE WHEN Statementoracle CASE WHEN 语句中如何查找重复记录
【发布时间】:2021-01-10 08:20:42
【问题描述】:

我有两张如下表。 TABLEA 和表 TABLEB。我们对 TRANS_ID 进行外连接并比较两个表。

我想得到结果中显示的结果。我们仅检查 TABLEA 中的重复项(即,基于 TABLEA.TRANS_ID)。

TABLEA
+------+----------+-------+--+-------------+
| UUID | TRANS_ID | NAME  |  | PHONENUMBER |
+------+----------+-------+--+-------------+
|  123 |     7928 | SCOTT |  | 87482837849 |
|  123 |     7928 | SCOTT |  | 87482837849 |
|  489 |     7493 | TOM   |  | 79274778397 |
|  827 |     7920 | DAVID |  | 23794928749 |
|  324 |     8472 | PAT   |  | 87927478839 |
+------+----------+-------+--+-------------+

TABLEB
+----------+----------+--------+-------------+
| BATCH_ID | TRANS_ID | SENDER | PHONENUMBER |
+----------+----------+--------+-------------+
|   823784 |     7438 | LSK    | 84748394092 |
|   793847 |     7493 | KLI    | 79274778397 |
|   748738 |     7920 | ISL    | 74892890487 |
+----------+----------+--------+-------------+

RESULT
+----------+-------------+-------------------------+
| TRANS_ID | PHONENUMBER |           STATUS        |
+----------+-------------+-------------------------+
|     7928 | 87482837849 |    DUPLICATE RECORD     |
|     7928 | 87482837849 |    NOT IN TABLEB        |
|     7438 | 84748394092 |    NOT IN TABLEA        |
|     7920 | 23794928749 |    PHONENUMBER MISMATCH |
|     8472 | 87927478839 |    NOT IN TABLEB        |
+----------+-------------+-------------------------+

我尝试使用以下 case when 语句。除了提取重复项外,我涵盖了所有场景。当 TABLE A 中存在重复记录且 TABLEB 中不存在重复记录时,第一条记录应为“NOT IN TABLEB”,后续记录应为“DUPLICATE RECORD”

 CASE
          WHEN TABLEA.TRANS_ID is null THEN 'NOT IN TABLEA'
          WHEN TABLEB.TRANS_ID is null THEN 'NOT IN TABLEB' 
          WHEN decode(TABLEA.PHONENUMBER,ALRAJHI_TABLEB.PHONENUMBER,1,0)=0 THEN 'PHONENUMBER MISMATCH'             
          END

【问题讨论】:

  • 为什么trans_id = 7928 一行显示DUPLICATE RECORD 和一行NOT IN TABLEB ?如果您说TABLEA 是主表,那么条件TABLEA.TRANS_ID is null 对我来说没有意义?
  • 对不起,这不是这两者之间的父子关系。有两个表有一些数据,可能的情况是表A中可以存在记录,但表B中不存在记录,反之亦然。只是为了比较重复项,我们只检查表 A 中的 trans_id 而不是表 B 中的。
  • 我建议您提供完整的 SQL 查询(而不仅仅是 CASE 部分)和您得到的当前结果,以帮助更好地了解您的问题。
  • 你使用FULL OUTER JOIN吗?
  • 看来你只需要ELSE 'DUPLICATE RECORD作为最后一种情况。

标签: sql oracle duplicates case-when


【解决方案1】:

这是一种方法:

WITH x
     AS (SELECT ROW_NUMBER()
                  OVER (
                    PARTITION BY CASE WHEN a.trans_id IS NULL THEN b.trans_id ELSE a.trans_id END
                    ORDER BY CASE WHEN a.trans_id IS NULL THEN b.trans_id ELSE a.trans_id END) AS rn,
                CASE WHEN a.trans_id IS NULL THEN b.trans_id ELSE a.trans_id END AS trans_id,
                CASE WHEN a.trans_id IS NULL THEN b.phonenumber ELSE a.phonenumber END AS phonenumber,
                CASE
                     WHEN a.trans_id IS NULL THEN 'NOT IN TABLEA'
                     WHEN b.trans_id IS NULL THEN 'NOT IN TABLEB'
                     WHEN DECODE(a.phonenumber, b.phonenumber, 1, 0) = 0 THEN 'PHONENUMBER MISMATCH'
                END AS status
         FROM   tablea a
                FULL OUTER JOIN tableb b
                             ON a.trans_id = b.trans_id),
y AS (
SELECT trans_id,
       phonenumber,
       CASE WHEN rn > 1 THEN 'DUPLICATE RECORD' ELSE status END AS status
FROM   x)
SELECT * FROM y
WHERE  status IS NOT NULL -- Exclude TableA records that are (presumably) OK

编辑:使用第二个 CTE (y) 作为 NOT NULL 过滤器的调整查询正在删除 ROW_NUMBER() 检查所需的行。

【讨论】:

  • 这很好用,但问题是当 TABLEA TRANS_ID '7928' 中的一条/两条记录都在 TABLEB 中时,我在结果中没有得到 'DUPLICATE RECORD'。
  • 您可以使用我在dbfiddle.uk/… 创建的小提琴中提供的示例数据检查结果。对于 Trans_ID 7928,第一个条目显示“不在 TableB 中”,而第二个条目(由 CASE WHEN rn > 1 条件拾取)标记为“重复记录”。也许您可以在小提琴中尝试一些额外的数据,看看您是否可以演示/重现您遇到的问题?
  • 你能检查一下我的小提琴吗?我在 tableA 和 tableB 中都有这条记录 7928,但它在 tableA 中是重复的。它不会在结果中显示为重复(实际上该记录根本没有出现)。 dbfiddle.uk/...
  • @Raj,谢谢你的例子。我已经修改了查询来处理这种情况。
  • 我很抱歉继续讨论这个问题。此修复程序有效,但是当我遇到这种情况时,例如此处的示例 dbfiddle.uk。我得到 8 条带有“DUPLICATE RECORD”标志的记录。实际上,我应该只得到三个 trans_id 为 7928 的记录,对吧?
【解决方案2】:

我想我会使用union all 从第一个表中引入重复项:

select trans_id, coalesce(ta.phonenumber, tb.phonenumber) as phonenumber,
       (case when ta.phonenumber is null then 'NOT IN TABLEA'
             when tb.phonenumber is null then 'NOT IN TABLEB'
             else 'PHONENUMBER MISMATCH'
        end) as status
from (select distinct trans_id, phonenumber
      from tablea ta
     ) ta full join
     tableb tb
     using (trans_id)
where ta.phonenumber is null or tb.phonenumber is null or
      ta.phonenumber <> tb.phonenumber
union all
select trans_id, phonenumber, 'DUPLICATE RECORD'
from tablea
group by trans_id, phonenumber
having count(*) >= 2;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2021-02-05
    • 2021-09-13
    • 2013-04-23
    • 2021-01-24
    相关资源
    最近更新 更多