从db表中删除冗余行

时间:2015-10-21 14:50:01

标签: mysql sql

我有一个像下面这样的数据库表(我知道设计不好,但是有很多这样的行):

person1    |    person2     |    counselor
Jane Doe   |    John Doe    |    Mary Smith
John Doe   |    Jane Doe    |    Mary Smith
Frank Jones|    Ann Jones   |    Tom Jones
Ann Jones  |    Frank Jones |    Tom Jones

我试图找出如何选择其中一个独特的'行,以便结果看起来像:

person1    |    person2     |    counselor
Jane Doe   |    John Doe    |    Mary Smith
Frank Jones|    Ann Jones   |    Tom Jones

我已经尝试了各种各样的事情,例如SELECT distinctSELECT MIN(person1)等,但我很惊讶。

3 个答案:

答案 0 :(得分:0)

你将有6个(person1,person2,辅导员)的排列,你可以使用union。最后使用where子句,这样每个组合只返回一行。

Fiddle with sample data

select * from (
select person1,person2,counselor 
from tablename
union 
select person1,counselor,person2 
from tablename
union
select person2,person1,counselor 
from tablename
union
select person2,counselor,person1
from tablename
union
select counselor,person2,person1
from tablename
union
select counselor,person1,person2
from tablename) t
where person1 < person2 and person2 < counselor

答案 1 :(得分:0)

SQL Fiddle Demo

我包含一个没有反向重复的情况,另一个情况是person1 = person2,还包括P2.*,仅用于调试。

SELECT P1.person1, P1.person2, P1.counselor, P2.*
FROM patient P1
LEFT JOIN patient P2
       ON P1.person1 = P2.person2
      AND P1.person2 = P2.person1
      AND P1.counselor = P2.counselor
WHERE 
   concat(P1.person1, P1.person2) <= concat(P2.person1, P2.person2)
OR P2.person1 is null

P2 is NULL表示没有person1, person2

的反向组合时

但是当组合存在时,只选择较小的一个作为字符串连接。

答案 2 :(得分:0)

With ranked_records AS
(
   select *, 
    ROW_NUMBER() OVER(Partition By person1, person2, counselor 
    Order By person) [ranked] 
    from address
)
select * from ranked_records
where ranked > 1

更多detail,例如如何删除最新记录并保留旧记录。

对于MySql,如果您有Id,请尝试:

DELETE A1
From Address A1
Where Exists (Select * From Address A2 
    Where A2.person1= A1.person1
    AND A2.person2 = A1.person2
    AND A2.counselor = A1.counselor 
    AND A1.AddressID > A2.AddressID)