选择具有多个必需过滤器的行

asy*_*ror 2 sql-server-2008 sql-server

我如何选择在其音乐流派中具有朋克和摇滚风格的艺术家?我需要两种类型的艺术家。

我的桌子

一个例子:

SELECT * FROM artist_genre WHERE genre_id IN (1,2)
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我恢复了所有属于朋克或摇滚的东西。但我只需要拥有两者的艺术家。有没有简单的方法呢?

如果需要更改数据库的结构,我可以做。

Han*_*non 5

这被称为集合交集。执行查询的一种方法是使用INTERSECT运算符

SELECT ag.artist_id 
FROM dbo.artists_genres ag
WHERE ag.genre_id = 1
INTERSECT
SELECT ag.artist_id 
FROM dbo.artists_genres ag
WHERE ag.genre_id = 2
Run Code Online (Sandbox Code Playgroud)

INTERSECT返回由左右输入输出的不同行。查询的第一部分检索流派_id 为1 的artist_id,查询的第二部分检索流派_id 为2 的artist_id,然后INTERSECT运算符比较两个列表,仅返回精确匹配的行,消除重复项。

这与INNER JOIN对两个公用表表达式(通常称为 CTE)使用 an 非常相似,如下所示:

;WITH g1 AS
(
    SELECT *
    FROM dbo.artists_genres ag1
    WHERE ag1.genre_id = 1
), g2 AS
(
    SELECT *
    FROM dbo.artists_genres ag1
    WHERE ag1.genre_id = 2
)
SELECT g1.artist_id
FROM g1
    INNER JOIN g2 ON g1.artist_id = g2.artist_id;
Run Code Online (Sandbox Code Playgroud)

如果您不喜欢公用表表达式 (CTE),则如下所示:

SELECT g1.artist_id
FROM
    (
        SELECT *
        FROM dbo.artists_genres ag1
        WHERE ag1.genre_id = 1
    ) g1
    INNER JOIN
        (
            SELECT *
            FROM dbo.artists_genres ag1
            WHERE ag1.genre_id = 2
        ) g2 ON g1.artist_id = g2.artist_id
Run Code Online (Sandbox Code Playgroud)