【问题标题】:Unable to get duplicate records from table无法从表中获取重复记录
【发布时间】:2017-08-13 10:32:43
【问题描述】:

我有一个表格,其结构如下:

User_ID 在特定时间间隔内具有其各自项目的值。项目值可以是文本或整数,具体取决于项目。

我想检查是否有两个或多个 UserId 作为相同的值,这意味着它们的项目具有相同的值和相同的时间间隔。

如上表 UserId 213456 和 UserId 213458 有相同的记录。 我尝试使用游标和循环,但时间太长了。我的表有超过 5000 万个 UserId。有没有办法以有效的方式做到这一点?

我也尝试将 group by 与子查询一起使用,但所有尝试都未能为其创建良好的查询。

我使用How do I find duplicate values in a table in Oracle?创建了以下查询

select t1.USERID, count(t1.USERID) 
from USERS_ITEM_VAL t1 
where exists ( select * 
               from  USERS_ITEM_VAL t2 
                where t1.rowid <> t2.rowid and 
                       t2.ITEMID = t1.ITEMID and 
                       t2.TEXT_VALUE = t1.TEXT_VALUE and 
                       --t2.INTEGER_VALUE = t1.INTEGER_VALUE and 
                       t2.INIT_DATE = t1.INIT_DATE and 
                      t2.FINAL_DATE = t1.FINAL_DATE )  
        group by t1.USERID having count(t1.USERID) > 1 order by count(t1.USERID);

但问题是它在排除 INTEGER_VALUE 列时工作,但当我在连接中包含 INTEGER_VALUE 列时不给我输出,尽管我在 INTEGER_VALUE 列中的数据是相同的。 这是我的表的结构:

USERID - NUMBER
ITEMID - NUMBER
TEXT_VALUE - VARCHAR2(500)
INTEGER_VALUE - NUMBER
INIT_DATE - DATE
FINAL_DATE - DATE 

【问题讨论】:

标签: sql oracle plsql


【解决方案1】:

解决此问题的一种方法是使用自联接。这个想法是计算两个用户共有的项目数(考虑日期列)。然后将其与每个项目的数量进行比较:

with t as (
      select t.*, count(*) over (partition by userid) as numitems
      from t
     )
select t1.userid, t2.userid
from t t1 join
     t t2
     on t1.userid < t2.userid and
        t1.itemid = t2.itemid and
        t1.init_date = t2.init_date and
        t1.final_date = t2.final_date and
        t1.numitems = t2.numitems
group by t1.userid, t2.userid, t1.numitems
having count(*) = t1.numitems;

【讨论】:

    【解决方案2】:

    您的查询失败的原因是 text_value 或 integer_value 在每一行中都将为 NULL。因此,如果不使用 NVL 函数插入 NULL 值,就无法在自连接中使用相等谓词。

    但是,下面是一个使用分析函数来实现目标的查询:

    Select * From (
    Select t.*, Count(*) Over (Partition By t.itemId, 
                                            t.text_value, 
                                            t.integer_value, 
                                            t.init_date, 
                                            t.final_date) as Cnt)
    Where cnt > 1;
    

    查询返回Partition By 子句的五列中多条记录具有相同值的所有行。

    与自联接方法相比,这种技术的一个好处是表只被扫描一次,而使用自联接时它会被扫描两次。如果表很大,这可能会带来更好的性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-21
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 2020-08-22
      相关资源
      最近更新 更多