【问题标题】:Oracle self join copying column value over different values in the same columnOracle自连接复制列值到同一列中的不同值
【发布时间】:2016-01-12 17:36:00
【问题描述】:

我正在尝试清理一些几乎重复的数据。我正在做一个自联接来查找除一列之外的所有列都相等的记录,这样我就可以找到最好的那些重复项以从表中删除。我遇到的问题是,虽然数字记录是正确的,但我只看到一个 id 列值一遍又一遍地重复。当我查看与该用户关联的所有值时,只有一次重复的 id 列值。

我知道这并不完全清楚,所以希望这会有所帮助。

Id1    ID2    AnotherColumn    AnotherColumn2
---------------------------------------------

1      345       "a"                "bd"
2      345       "a"                "bd"
3      345       "a"                "bd"
4      345       "a"                "bd"
5      345       "a"                "bd"

我想要返回的是与您在这个虚拟表中看到的完全一样的所有内容。我得到的是这样的:

Id1    ID2    AnotherColumn    AnotherColumn2
---------------------------------------------

1      345       "a"                "bd"
1      345       "a"                "bd"
1      345       "a"                "bd"
1      345       "a"                "bd"
1      345       "a"                "bd"

我使用的查询如下所示:

select A.Id1, A.ID2, A.AnotherColumn, A.AnotherColumn2
from dummy_table A, dummy_table B
where A.ID2 = B.ID2
AND A.Id1 <> B.Id1
AND A.AnotherColumn = B.AnotherColumn
AND A.AnotherColumn2 = B.AnotherColumn2

我想知道的是为什么 Id1 的值被复制到其他行而不是实际显示的原始 Id1 值。

我需要从该表中列出符合这些条件的 id,因为我必须将它们从包含不符合这些条件的其他记录的原始表中删除,这些记录需要保持不变。

【问题讨论】:

    标签: sql oracle join self-join


    【解决方案1】:

    当我运行您的查询时,我得到了 20 行;每个 id1 值 4(与 4 x 5 相同,因为您实际上是在进行交叉连接,仅排除 a.id1 = b.id1 的行)。

    with dummy_table as (select 1 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual union all
                         select 2 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual union all
                         select 3 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual union all
                         select 4 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual union all
                         select 5 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual)
    select A.Id1, A.ID2, A.AnotherColumn, A.AnotherColumn2
    from dummy_table A, dummy_table B
    where A.ID2 = B.ID2
    AND A.Id1 <> B.Id1
    AND A.AnotherColumn = B.AnotherColumn
    AND A.AnotherColumn2 = B.AnotherColumn2
    order by 1, 2, 3, 4
    
    
           ID1        ID2 ANOTHERCOLUMN ANOTHERCOLUMN2
    ---------- ---------- ------------- --------------
             1        345 a             bd            
             1        345 a             bd            
             1        345 a             bd            
             1        345 a             bd            
             2        345 a             bd            
             2        345 a             bd            
             2        345 a             bd            
             2        345 a             bd            
             3        345 a             bd            
             3        345 a             bd            
             3        345 a             bd            
             3        345 a             bd            
             4        345 a             bd            
             4        345 a             bd            
             4        345 a             bd            
             4        345 a             bd            
             5        345 a             bd            
             5        345 a             bd            
             5        345 a             bd            
             5        345 a             bd
    

    但是,我想知道你是否在追求类似的东西:

    with dummy_table as (select 1 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual union all
                         select 2 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual union all
                         select 3 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual union all
                         select 4 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual union all
                         select 5 id1, 345 ID2, 'a' AnotherColumn, 'bd' AnotherColumn2 from dual union all
                         select 6 id1, 345 ID2, 'b' AnotherColumn, 'bd' AnotherColumn2 from dual)
    select id1,
           id2,
           anothercolumn,
           anothercolumn2
    from   (select id1,
                   id2,
                   anothercolumn,
                   anothercolumn2,
                   count(*) over (partition by id2, anothercolumn, anothercolumn2) cnt
            from   dummy_table)
    where  cnt > 1;
    
           ID1        ID2 ANOTHERCOLUMN ANOTHERCOLUMN2
    ---------- ---------- ------------- --------------
             1        345 a             bd            
             2        345 a             bd            
             3        345 a             bd            
             4        345 a             bd            
             5        345 a             bd 
    

    您可能根本不需要分析函数 - 要删除除具有最低 id1 的行之外的所有行,您可以执行以下操作:

    delete from dummy_table
    where id1 not in (select min(id1) from dummy_table group by id2, anothercolumn, anothercolumn2);
    

    【讨论】:

    • 谢谢,我最终做了与您提供的第一个选项非常相似的事情。
    【解决方案2】:

    我认为这会满足您的需求:

    select min(A.id) over (partition by A.ID2, A.AnotherColumn, A.AnotherColumn2) as id,
           A.id2, A.AnotherColumn, A.AnotherColumn2
    from dummy_table A;
    

    这将为partition by 子句中的列组合返回最小值id

    【讨论】:

    • 如何处理与我发布的表格类似的表格,但包含多组此类数据以及不符合该标准的数据?我想选择符合这些条件的数据,然后选择 Id1 列的最大值作为记录以保留并删除其余部分。抱歉,我对分区一点也不熟悉。
    猜你喜欢
    • 2019-07-27
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    相关资源
    最近更新 更多