SQL窗口函数 - 按限制选择DISTINCT ORDER

时间:2013-04-19 19:27:59

标签: sql performance postgresql window-functions postgresql-performance

我在PostgreSQL数据库中有这3个表:

  • 艺术家: id,name
  • 相册:ID,title,year,artist_id
  • 歌曲: id,title,album_id

基本上每位艺术家都有多张专辑,每张专辑都有多首歌曲。

我的查询正确地返回了25个不同的artist.id,他们的歌曲的标题以“The”开头,以相册的年份排序:

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时,它会停止搜索。

可以重写或优化此查询以更快地执行吗?

我认为window functions可以在这里加快速度,但我无法找到有用的东西。

谢谢!

3 个答案:

答案 0 :(得分:1)

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

song.title上的索引可以在ilike表达式以%

开头时提供帮助

答案 1 :(得分: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

答案 2 :(得分:0)

试试这个,

Select id, year
from (
    SELECT DISTINCT ON (artist.id) artist.id, album.year
    FROM artist
    rightJOIN album ON album.artist_id = artist.id
    left 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