SQL中的过滤器重复连接
问题描述:
使用SQL连接时,是否可以只保留左表中只有一行的行?SQL中的过滤器重复连接
例如:
select * from A, B where A.id = B.a_id;
a1 b1
a2 b1
a2 b2
在这种情况下,我想除了第一行,所有的删除,其中从A精确匹配1行中的一行从B.
我使用MySQL 。
答
这应该在MySQL的工作:
select * from A, B where A.id = B.a_id GROUP BY A.id HAVING COUNT(*) = 1;
对于那些不使用MySQL,则需要对所有列使用聚合函数(如MIN()或MAX())(除A. ID),所以你的数据库引擎不会抱怨。
答
如果您在提出这样的问题时指定了表格的键,它会有所帮助。从你的例子中看不出什么是B的关键(假设它有一个)。
这里是一个可能的解决方案假设ID是表B的候选键
SELECT *
FROM A, B
WHERE B.id =
(SELECT MIN(B.id)
FROM B
WHERE A.id = B.a_id);
答
首先,我会建议使用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
)
答
这避免计数匹配行的成本,这对于大表昂贵。
像往常一样,当比较各种可能的解决方案时,建议对基准/比较执行计划。
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
)
如果B有超过1个匹配的行,它不能正常工作。你需要删除HAVING子句,然后它应该没问题(尽管我绝对推荐总是对任何非GROUPed列使用聚合函数)。致歉, – sqlvogel 2010-06-12 21:44:05
。我似乎误解了想要的东西。它看起来像你的查询是好的,我不是,但以防万一它帮助我让我的立场现在:) – sqlvogel 2010-06-12 21:48:58