我有一组包含许多列的行。例如,
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
但是,我希望避免这种情况,因为在某些情况下我有太多列,并且很容易出错。
解决这个问题的最佳方法是什么?
答案 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