2010-06-12 85 views
3

使用SQL连接时,是否可以只保留左表中只有一行的行?SQL中的过滤器重复连接

例如:

select * from A, B where A.id = B.a_id; 

a1 b1 
a2 b1 
a2 b2 

在这种情况下,我想除了第一行,所有的删除,其中从A精确匹配1行中的一行从B.

我使用MySQL 。

回答

4

这应该在MySQL的工作:

select * from A, B where A.id = B.a_id GROUP BY A.id HAVING COUNT(*) = 1; 

对于那些不使用MySQL,则需要对所有列使用聚合函数(如MIN()或MAX())(除A. ID),所以你的数据库引擎不会抱怨。

+0

如果B有超过1个匹配的行,它不能正常工作。你需要删除HAVING子句,然后它应该没问题(尽管我绝对推荐总是对任何非GROUPed列使用聚合函数)。致歉, – sqlvogel 2010-06-12 21:44:05

+0

。我似乎误解了想要的东西。它看起来像你的查询是好的,我不是,但以防万一它帮助我让我的立场现在:) – sqlvogel 2010-06-12 21:48:58

0

如果您在提出这样的问题时指定了表格的键,它会有所帮助。从你的例子中看不出什么是B的关键(假设它有一个)。

这里是一个可能的解决方案假设ID是表B的候选键

SELECT * 
FROM A, B 
WHERE B.id = 
(SELECT MIN(B.id) 
    FROM B 
    WHERE A.id = B.a_id); 
0

首先,我会建议使用JOIN语法,而不是用逗号分隔的表过时的语法。其次,如果A.id是表A的主键,那么你只需要检查表B的重复:

Select ... 
From A 
    Join B 
     On B.a_id = A.id 
Where Exists (
       Select 1 
       From B B2 
       Where B2.a_id = A.id 
       Having Count(*) = 1 
       ) 
0

这避免计数匹配行的成本,这对于大表昂贵。

像往常一样,当比较各种可能的解决方案时,建议对基准/比较执行计划。

select 
    * 
from 
    A 
    join B on A.id = B.a_id 
where 
    not exists (
    select 
     1 
    from 
     B B2 
    where 
     A.id = b2.a_id 
     and b2.id != b.id 
)