Sky*_*ell -1 t-sql sql-server join
我有一个表,hs_book其中有一列名为GENRE_ID
我从一个名为的表中获取该类型的描述GENRE
我的列子查询Genre:
SELECT *,
Genre = (
SELECT DESCRIPTION
FROM GENRE
WHERE GENRE_ID = (
SELECT TOP 1 GENRE_ID
FROM BOOK_GENRES
WHERE BOOK_ID = hs_book.BOOK_ID
)
)
FROM hs_book
Run Code Online (Sandbox Code Playgroud)
当我执行此查询时,我得到 525 本书(这是正确的)。
应高级 DBA 的要求,我尝试将其转换为 JOIN,这样我就不需要子查询,所以我这样做了:
SELECT * FROM hs_book hsb
INNER JOIN BOOK_GENRES bg ON hsb.BOOK_ID = bg.BOOK_ID
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我得到了 541 个结果,比子查询多了 16 个结果。
经过查资料,我发现有些书有多个GENRE_IDs.
有没有办法修改我的加入,以便我只为每本书返回一种类型?
您需要确保BOOK_GENRES每个返回一行BOOK_ID。
SELECT
hsb.ID,
hsb.Name,
STRING_AGG(bg.Genre, ', ') Genre
FROM hs_book hsb
INNER JOIN BOOK_GENRES bg ON hsb.BOOK_ID = bg.BOOK_ID
GROUP BY
hsb.ID,
hsb.Name;
Run Code Online (Sandbox Code Playgroud)
SELECT
hsb.ID,
hsb.Name,
bg.Genre
FROM hs_book hsb
INNER JOIN (
SELECT
bg.BOOK_ID,
STRING_AGG(bg.Genre, ', ') Genre
FROM BOOK_GENRES bg
GROUP BY
bg.BOOK_ID
) bg ON hsb.BOOK_ID = bg.BOOK_ID;
Run Code Online (Sandbox Code Playgroud)
您也可以使用APPLY.
SELECT
hsb.ID,
hsb.Name,
bg.Genre
FROM hs_book hsb
CROSS APPLY (
SELECT
STRING_AGG(bg.Genre, ', ') Genre
FROM BOOK_GENRES bg
WHERE hsb.BOOK_ID = bg.BOOK_ID
GROUP BY
()
) bg;
Run Code Online (Sandbox Code Playgroud)
ROW_NUMBER它来过滤。如果您不关心哪个顺序,则使用ORDER BY (SELECT NULL).SELECT
hsb.ID,
hsb.Name,
bg.Genre
FROM hs_book hsb
INNER JOIN (
SELECT
BG.BOOK_ID,
bg.Genre,
ROW_NUMBER() OVER (PARTITION BY bg.BOOK_ID ORDER BY bg.Genre) rn
FROM BOOK_GENRES bg
) bg ON hsb.BOOK_ID = bg.BOOK_ID AND bg.rn = 1;
Run Code Online (Sandbox Code Playgroud)
前三个选项可能具有相同的性能,因为编译器通常可以在它们之间进行转换。
最后一个可能与您最初的查询类似。
请注意,它们的语义与原始语义略有不同,因为它们使用INNER JOIN和CROSS APPLY。您可能想切换到LEFT JOIN或OUTER APPLY。
| 归档时间: |
|
| 查看次数: |
59 次 |
| 最近记录: |