我有2列,name1和name2,它们包含许多可能名称的行。
例如:John Citizen,Jane Taxpayer,Citizen John,Taxpayer Jane等......
一个部分名称存储在name1下,另一个部分名称存储在name2下。我想知道如何删除表中出现的所有名称,以便每个可能的名称只有一个条目?例如John Citizen或Citizen John将存在,但不是两者都存在。所以最后我会得到:
John Citizen
Jane Taxpayer
...或
John Citizen
Taxpayer Jane
...或
Citizen John
Taxpayer Jane
...或
Citizen John
Jane Taxpayer
编辑:只是为了澄清,例如,name1 = John,name2 = Citizen。它们已被分解为各自的列,因此我只需要在两列之间选择唯一的组合。
答案 0 :(得分:1)
n
:
create table n(f varchar(10), l varchar(10), primary key(f,l));
以下10行:
'alfred', 'hitchcock'
'hitchcock', 'alfred'
'john', 'doe'
'doe', 'john'
'edward', 'scissorhan'
'felix', 'leclerc'
'lane', 'penny'
'penny', 'lane'
此查询将仅返回没有反转的名称:
SELECT u1.f, u1.l
FROM n u1
LEFT JOIN n u2
ON (u1.f=u2.l AND u1.l=u2.f)
WHERE u2.f IS NULL and u2.l IS NULL;
'edward', 'scissorhan'
'felix', 'leclerc'
此查询将仅返回具有反转(和反转)的名称:
SELECT u1.f, u1.l
FROM n u1 JOIN n u2
ON (u1.f=u2.l AND u1.l=u2.f);
'alfred', 'hitchcock'
'doe', 'john'
'hitchcock', 'alfred'
'john', 'doe'
'lane', 'penny'
'penny', 'lane'
因此,我们需要使用的集合由上面的查询创建。如果我们决定我们只想要u1.f<的行。 u2.f,然后我们有一个过滤器,它给我们一个独特的集合:
SELECT u1.f, u1.l
FROM n u1
JOIN n u2
ON (u1.f=u2.l AND u1.l=u2.f)
WHERE u1.f<=u2.f;
答案 1 :(得分:0)
您可以执行自联接以查找匹配的行对,然后通过区分两个名称列之一来任意选择要删除的行。如果你有一个主键,你可以区分它,但我没有在你的例子中看到一个。
如果你还没有一个索引,你还应该在(fname,lname)上添加一个唯一索引,以防止插入完全重复的内容。
假设您有(fname,lname)上的唯一索引,此查询应该适合您:
DELETE t2.*
FROM uniquenames t1
INNER JOIN uniquenames t2
ON t2.lname = t1.fname AND t2.fname = t1.lname AND t2.fname < t1.fname
请注意,如果您(fname,lname)上没有唯一索引,那么您可以有两行完全重复。例如“Kyle Kyle”和“Kyle Kyle”。我的删除声明不会删除这两行。如果你有一个简单的主键,但我没有在你的例子中看到一个。