使用嵌套的 group-by/having 子句进行复杂连接?
Posted
技术标签:
【中文标题】使用嵌套的 group-by/having 子句进行复杂连接?【英文标题】:Complex join with nested group-by/having clause? 【发布时间】:2010-10-09 09:56:40 【问题描述】:我最终需要包含“专辑”的“导入”记录列表 每张唱片只有一首“歌曲”。
这是我现在使用的:
select i.id, i.created_at
from imports i
where i.id in (
select a.import_id
from albums a inner join songs s on a.id = s.album_id
group by a.id having 1 = count(s.id)
);
嵌套选择(带有连接)非常快,但外部 "in" 子句非常慢。
我尝试将整个查询设为单个(无嵌套)连接,但运行了 成组/有子句的问题。我能做的最好的就是 带有欺骗性的“导入”记录列表,这是不可接受的。
有没有更优雅的方式来编写这个查询?
【问题讨论】:
您会指定 RDBMS 吗? 【参考方案1】:未经测试:
select
i.id, i.created_at
from
imports i
where
exists (select *
from
albums a
join
songs s on a.id = s.album_id
where
a.import_id = i.id
group by
a.id
having
count(*) = 1)
或
select
i.id, i.created_at
from
imports i
where
exists (select *
from
albums a
join
songs s on a.id = s.album_id
group by
a.import_id, a.id
having
count(*) = 1 AND a.import_id = i.id)
【讨论】:
【参考方案2】:怎么样?
SELECT i.id,
i.created_at
FROM imports i
INNER JOIN (SELECT a.import_id
FROM albums a
INNER JOIN songs s
ON a.id = s.album_id
GROUP BY a.id
HAVING Count(* ) = 1) AS TEMP
ON i.id = TEMP.import_id;
在大多数数据库系统中,JOIN 的工作速度比 WHERE ... IN 快。
【讨论】:
这已经足够接近了。我必须添加“按 i.id,i.created_at 分组”以实现“无重复”要求(参见原始帖子)。谢谢。 是的,我错过了。没问题。【参考方案3】:SELECT i.id, i.created_at, COUNT(s.album_id)
FROM imports AS i
INNER JOIN albums AS a
ON i.id = a.import_id
INNER JOIN songs AS s
ON a.id = s.album_id
GROUP BY i.id, i.created_at
HAVING COUNT(s.album_id) = 1
(您可能不需要将COUNT
包含在SELECT
列表本身中。SQL Server 不需要它,但不同的RDBMS 可能会这样做。)
【讨论】:
【参考方案4】:所有三种建议的技术都应该比您的 WHERE IN 更快:
-
存在相关子查询 (gbn)
内部连接的子查询 (achinda99)
内连接所有三个表 (luke)
(所有这些都应该可以工作......,所以对所有这些都 +1。如果其中一个不起作用,请告诉我们!)
实际上哪个速度最快,取决于您的数据和执行计划。但这是一个有趣的例子,展示了用 SQL 表达同一事物的不同方式。
【讨论】:
【参考方案5】:我试图使整个查询 单(无嵌套)连接但遇到 小组/有问题 条款。
如果您使用的是 SQL Server 版本 2005/2008,则可以使用 CTE(公用表表达式)加入子查询
据我所知,CTE 只是一个表达式,它的工作方式类似于一个虚拟视图,仅适用于单个 select 语句 - 因此您将能够执行以下操作。 我通常发现使用 CTE 也可以提高查询性能。
with AlbumSongs as (
select a.import_id
from albums a inner join songs s on a.id = s.album_id
group by a.id
having 1 = count(s.id)
)
select i.id, i.created_at
from imports i
inner join AlbumSongs A on A.import_id = i.import_id
【讨论】:
以上是关于使用嵌套的 group-by/having 子句进行复杂连接?的主要内容,如果未能解决你的问题,请参考以下文章