4

PostgreSQL データベースに次の 3 つのテーブルがあります。

  • アーティスト: ID、名前
  • アルバム: id、タイトル、年、artist_id
  • 曲: id、タイトル、album_id

基本的に各アーティストには複数のアルバムがあり、各アルバムには複数の曲があります。

私のクエリは、タイトルが「The」で始まる曲を持つ 25 個の異なる artist.id を、アルバムの年順に正しく返します。

SELECT id
FROM (

    -- Remove the duplicate artists
    SELECT DISTINCT ON (a.id) id, row
    FROM (

        -- Get all matching artists 
        -- This is slow because there is no limit
        SELECT
            artist.id,
            row_number() OVER(ORDER BY album.year DESC) as row
        FROM artist
        LEFT JOIN album ON album.artist_id = artist.id
        LEFT JOIN song ON song.album_id = album.id
        WHERE song.title ilike 'The %'
        ORDER BY album.year DESC

    ) as a

) as b
ORDER BY row
LIMIT 25

ただし、最も内側のクエリには LIMIT がないため、テーブル全体で可能なすべての一致を検索するため、遅くて非効率的です。理想的には、25 個の異なる artist.id が見つかったときに検索を停止します。

このクエリを書き直すか最適化して、より高速に実行できますか?

ここでウィンドウ関数を使用すると速度が向上すると思いますが、機能するものを見つけることができませんでした。

ありがとう!

4

3 に答える 3

2
select id, year
from (
    SELECT DISTINCT ON (artist.id) artist.id, album.year
    FROM artist
    inner JOIN album ON album.artist_id = artist.id
    inner JOIN song ON song.album_id = album.id
    WHERE song.title ilike 'The %'
    ORDER BY artist.id, album.year DESC
) s
order by year desc
LIMIT 25

インデックス onsong.titleは、ilike 式が%

于 2013-04-19T19:38:57.097 に答える
0

これを試してみてください。現在のクエリよりも速く動作するはずです

SELECT
  artist.id,                        
  MAX( album.year ) as latest_album_date
FROM 
  artist
  JOIN album ON album.artist_id = artist.id  -- JOIN, not LEFT JOIN
  JOIN song ON song.album_id = album.id      -- Since you have song.title in WHERE clause, it makes no sense to make these as a LEFT JOIN
WHERE 
  song.title ilike 'The %'
GROUP BY
  artist.id
ORDER BY
  latest_album_date DESC
limit 25;

SQLFIDDLE

于 2013-04-20T04:22:52.133 に答える