Oracle SQL如何在不同的列中查找重复值?

时间:2017-07-13 16:50:11

标签: sql oracle

我有一组包含许多列的行。例如,

ID | Col1 | Col2 | Col3 | Duplicate
------------------------------------
81 | 101  | 102  | 101  | YES
82 | 101  | 103  | 104  | NO

我需要计算“重复”列。它是重复的,因为它在Col1和Col3中具有相同的值。我知道有LEAST函数,类似于MIN函数,但有列。是否存在类似的事情?

我想到的方法是在这样的情况下编写所有可能的组合:

SELECT ID, col1, col2, col3, 
       CASE WHEN col1 = col2 or col1 = col3 or col2 = col3 then 1 else 0 end as Duplicate
FROM table

但是,我希望避免这种情况,因为在某些情况下我有太多列,并且很容易出错。

解决这个问题的最佳方法是什么?

6 个答案:

答案 0 :(得分:3)

嗯。您正在寻找行内重复项。这很痛苦。更新版本的Oracle支持横向连接。但是对于少数几个非NULL列,您可以这样做:

select id, col1, col2, col3,
       (case when col1 in (col2, col3) or col2 in (col3) then 1 else 0 end) as Duplicate
from t;

对于每个其他列,您需要再添加一个in比较并更新其他列表。

答案 1 :(得分:1)

这样的事情......请注意,在lateral子句中,我们仍然需要取消忽略,但这一次只有一行 - 导致执行速度比简单unpivot和标准聚合快得多

with
     input_data ( id, col1, col2, col3 ) as (
       select 81, 101, 102, 101 from dual union all
       select 82, 101, 103, 104 from dual
     )
-- End of simulated input data (for testing purposes only).
-- Solution (SQL query) begins BELOW THIS LINE.
select i.id, i.col1, i.col2, i.col3, l.duplicates
from   input_data i,
         lateral ( select  case when count (distinct val) = count(val) 
                                then 'NO' else 'YES'
                           end  as duplicates
                   from    input_data
                   unpivot ( val for col in ( col1, col2, col3 ) )
                   where   id = i.id
                 ) l
;

ID  COL1  COL2  COL3  DUPLICATES
--  ----  ----  ----  ----------
81   101   102   101  YES
82   101   103   104  NO 

答案 2 :(得分:0)

最佳方式是为了避免存储重复的列组。如果您有多个列基本上存储可比数据(即多值属性),请将数据移动到从属表,并使用一列。

CREATE TABLE child (
 ref_id INT,
 col INT
);

INSERT INTO child VALUES
(81, 101), (81, 102), (81, 101),
(82, 101), (82, 103), (82, 104);

然后,更容易找到值不止一次出现的情况:

SELECT id, col, COUNT(*)
FROM child
GROUP BY id, col
HAVING COUNT(*) > 1;

如果无法更改表的结构,可以使用UNIONs模拟它:

SELECT id, col1, COUNT(*)
FROM (
    SELECT id, col1 AS col FROM mytable
    UNION ALL SELECT id, col2 FROM mytable
    UNION ALL SELECT id, col3 FROM mytable
    ... for more columns ...
) t
GROUP BY id, col
HAVING COUNT(*) > 1;

最适合您尝试运行的查询。对于其他类型的查询,非规范化存储策略可能更好。

答案 3 :(得分:0)

您可以通过unpivot然后计算每个id的不同值并检查它是否等于该id的行数来执行此操作。平等意味着没有重复。然后left join将此结果发送到原始表,以便重复列。

SELECT t.*,
       CASE WHEN x.id IS NOT NULL THEN 'Yes' ELSE 'No' END AS duplicate
FROM t
LEFT JOIN
  (SELECT id
   FROM
     (SELECT *
      FROM t 
      unpivot (val FOR col IN (col1,col2,col3)) u 
     ) t
   GROUP BY id
   HAVING count(*)<>count(DISTINCT val)
  ) x ON x.id=t.id

答案 4 :(得分:0)

SELECT ID, col1, col2, 
    NVL2(NULLIF(col1, col2), 'Not duplicate', 'Duplicate')
       FROM table;

如果要比较2列以上,可以使用COALESCE

实现相同的逻辑

答案 5 :(得分:0)

我认为您想使用不包含表格内任何重复值的新数据,如果正确则使用SELECT DISTINCT语句,如

SELECT DISTINCT * FROM TABLE_NAME

它将包含重复的免费数据,
注意:它也适用于特定列,如

SELECT DISTINCT col1 FROM TABLE_NAME