Sql 是否使用嵌套的group by/having子句进行复杂联接?

Sql 是否使用嵌套的group by/having子句进行复杂联接?,sql,join,group-by,having,Sql,Join,Group By,Having,我最终需要一个包含唱片集的导入记录列表 每首歌只有一首的唱片 这就是我现在使用的: 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) ); 带有连接的嵌套select非常快速,但是外部

我最终需要一个包含唱片集的导入记录列表 每首歌只有一首的唱片

这就是我现在使用的:

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)
);
带有连接的嵌套select非常快速,但是外部 in子句的速度慢得令人痛苦

我试图使整个查询成为单个无嵌套联接,但运行了 与组/具有子句有关的问题。我所能做的就是 包含重复项的导入记录列表,这是不可接受的

有没有更优雅的方法来编写此查询?

未经测试:

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
       where
           a.import_id = i.id
       group by
           a.id
       having
           count(*) = 1)

这个怎么样

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; 
在大多数数据库系统中,连接比执行WHERE。。。这个怎么样

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; 
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
在大多数数据库系统中,连接比执行WHERE。。。在

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
您可能不需要将计数包含在选择列表中。SQL Server不需要它,但可能会使用不同的RDBMS


您可能不需要将计数包含在选择列表中。SQL Server不需要它,但有可能是不同的RDBMS。

所有三种建议的技术都应该比您的WHERE IN更快:

存在相关子查询gbn 内部联接到DA99的子查询 内部连接所有三个表 所有这些都应该起作用,所以所有这些都是+1。如果其中一个不起作用,请告诉我们


哪一个最快,取决于您的数据和执行计划。但是,这是一个有趣的例子,说明了在SQL中表达同一事物的不同方式。

所有三种建议的技术都应该比WHERE in更快:

存在相关子查询gbn 内部联接到DA99的子查询 内部连接所有三个表 所有这些都应该起作用,所以所有这些都是+1。如果其中一个不起作用,请告诉我们

哪一个最快,取决于您的数据和执行计划。但这是一个有趣的例子,说明了在SQL中表达同一事物的不同方式

我试着把整个问题都解释清楚 单个无嵌套联接但遇到 群体问题/有 条款

如果使用的是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
我试着把整个问题都解释清楚 单个无嵌套联接但遇到 群体问题/有 条款

如果使用的是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

你会指定RDBMS吗?你会指定RDBMS吗?这已经足够接近了。我必须通过I.id添加组,I.created_at以实现无重复要求,请参见原始帖子。谢谢,是的,我错过了。没问题,这已经够近了。我必须通过I.id添加组,I.created_at以实现无重复要求,请参见原始帖子。谢谢,是的,我错过了。没问题。