从 SQL Join 中删除重复项
Posted
技术标签:
【中文标题】从 SQL Join 中删除重复项【英文标题】:Removing duplicates from SQL Join 【发布时间】:2011-08-16 20:28:47 【问题描述】:以下是与我的实际问题接近的假设情况。 Table1
recid firstname lastname company
1 A B AAA
2 D E DEF
3 G H IJK
4 A B ABC
我有一个看起来像这样的 table2
recid firstname lastname company
10 A B ABC
20 D E DEF
30 M D DIM
40 A B CCC
现在如果我加入recid
上的表格,它将给出0
结果,不会有重复,因为recid
是唯一的。但是,如果我加入 firstname
和 lastname
列,它们不是唯一的并且有重复项,我会在内部连接中得到重复项。我在加入时添加的列越多,它变得越糟糕(创建的重复项越多)。
在上述简单的情况下,如何删除以下查询中的重复项?我想比较firstname
和lastname
,如果它们匹配,我从table2
返回firstname
、lastname
和recid
SELECT DISTINCT * FROM
(SELECT recid, first, last FROM table1) a
INNER JOIN
(SELECT recid, first,last FROM table2) b
ON a.first = b.first
如果以后有人想玩,脚本就在这里
CREATE TABLE table1 (recid INT NOT NULL PRIMARY KEY, first varchar(20), last varchar(20), company varchar(20))
CREATE TABLE table2 (recid INT NOT NULL PRIMARY KEY, first varchar(20), last varchar(20), company varchar(20))
INSERT INTO TABLE1 VALUES(1,'A','B','ABC')
INSERT INTO TABLE1 VALUES(2,'D','E','DEF')
INSERT INTO TABLE1 VALUES(3,'M','N','MNO')
INSERT INTO TABLE1 VALUES(4,'A','B','ABC')
INSERT INTO TABLE2 VALUES(10,'A','B','ABC')
INSERT INTO TABLE2 VALUES(20,'D','E','DEF')
INSERT INTO TABLE2 VALUES(30,'Q','R','QRS')
INSERT INTO TABLE2 VALUES(40,'A','B','ABC')
【问题讨论】:
您需要返回 reci - 如果不需要,从查询中删除它可以解决您的问题。 是的,否则我已经完成了剩下的工作。 您需要确定非重复行的逻辑。 CompanyId 和 RecId 对于您的骗子来说是不同的。您想保留哪些> @Savage:所以,在上面的例子中,你的结果应该是recid: 10,20,40
的三行?
@Savage Garden:你试过我的查询了吗?
【参考方案1】:
您本身并不想进行连接,您只是在测试存在/集合包含。
我不知道您正在编写的当前 SQL 风格是什么,但这应该可以。
SELECT MAX(recid), firstname, lastname
FROM table2 T2
WHERE EXISTS (SELECT * FROM table1 WHERE firstname = T2.firstame AND lastname = T2.lastname)
GROUP BY lastname, firstname
如果您想实现为联接,则代码大致相同:
即
SELECT max(t2.recid), t2.firstame, t2.lastname
FROM Table2 T2
INNER JOIN Table1 T1
ON T2.firstname = t1.firstname and t2.lastname = t1.lastname
GROUP BY t2.firstname, t2.lastname
根据 DBMS,内部连接的实现方式可能与 Exists 不同(半连接与连接),但优化器有时可以找出它并选择正确的运算符,无论您以哪种方式编写它。
【讨论】:
他的示例代码从两个数据集中都有一个 select * 但他的描述说“我想比较名字和姓氏,如果它们匹配,我返回名字、姓氏和 recifrom table2" 就是这样。我想我不需要加入,但如果可能的话,有人可以在加入中解释它吗? 他使用来自INNER JOIN
ed 结果集中的SELECT DISTINCT *
的示例代码非常清楚地表明他想要来自两个表的数据。如果我错了并且他澄清了我会很乐意删除 DV。
在我的情况下,它可以在没有MAX(recid)
(原始查询)的情况下工作。第二个查询不会产生相同的结果。不过还是谢谢。【参考方案2】:
SELECT t2.recid, t2.first, t2.last
FROM table1 t1
INNER JOIN table2 t2 ON t1.first = t2.first AND t1.last = t2.last
GROUP BY t2.recid, t2.first, t2.last
编辑:添加图片
【讨论】:
我尝试了类似于我的原始查询,但由于某种原因没有工作,谢谢。 @Savage Garden:你的意思是我提供的查询不起作用?图像是否代表错误的结果集? 它确实有效。问题是我只想保持 reci 的唯一性。其余的可以重复。就像我不想按 t2.first 和 t2.last 分组一样。但是使用 group by,你必须使用它。【参考方案3】:在某些情况下,您必须在子查询中进行分组
SELECT distinct b.recid, b.first, b.last
FROM table1 a
INNER JOIN (
SELECT MAX(recid) as recid, first, last
FROM table2
GROUP BY first, last
) b
ON a.first = b.first AND a.last = b.last
【讨论】:
以上是关于从 SQL Join 中删除重复项的主要内容,如果未能解决你的问题,请参考以下文章
如何修改此工作 SQL SELECT/JOIN 查询以删除重复项?