PostgreSQL无LIMIT等子句查询:找出Louis Armstrong之后去世的首位艺术家
解决PostgreSQL无LIMIT条件下的查询需求
没问题,我来帮你调整这个查询,去掉LIMIT子句同时实现“找出去世时间晚于Louis Armstrong的首位艺术家”的目标。首先咱们先明确核心逻辑:先定位Louis的去世年份,再筛选出所有去世年份晚于他的个人艺术家,最后选出其中去世最早的那一位。
优化思路说明
原查询的方向是对的,但依赖LIMIT 1来取首位。我们可以用两种替代方案实现,完全避开禁用的子句:
方案一:嵌套子查询定位最小符合条件的去世年份
这种方式通过两次子查询,先拿到Louis的去世年份,再找到比这个年份大的最小去世年份,最后筛选出对应艺术家:
SELECT A.NAME, CONCAT_WS('/', A.BEGIN_DATE_DAY::text, A.BEGIN_DATE_MONTH::text, A.BEGIN_DATE_YEAR::text) AS DATA_NASCITA, CONCAT_WS('/', A.END_DATE_DAY::text, A.END_DATE_MONTH::text, A.END_DATE_YEAR::text) AS DATA_MORTE FROM artist AS A JOIN artist_type AS AT ON A.TYPE = AT.ID WHERE AT.NAME LIKE 'Per%' -- 匹配个人艺术家 AND A.END_DATE_YEAR = ( -- 找到所有去世年份晚于Louis的个人艺术家中最小的去世年份 SELECT MIN(sub.END_DATE_YEAR) FROM artist AS sub JOIN artist_type AS sub_at ON sub.TYPE = sub_at.ID WHERE sub_at.NAME LIKE 'Per%' AND sub.END_DATE_YEAR > ( -- 精准获取Louis Armstrong的去世年份(比LIKE更可靠) SELECT louis.END_DATE_YEAR FROM artist AS louis JOIN artist_type AS louis_at ON louis.TYPE = louis_at.ID WHERE louis_at.NAME LIKE 'Per%' AND louis.NAME = 'Louis Armstrong' ) )
注:如果存在多位同年去世的艺术家,这个查询会返回所有符合的;如果需要唯一结果,可以把比较逻辑扩展到完整日期(结合END_DATE_MONTH和END_DATE_DAY)。
方案二:窗口函数排名筛选
用ROW_NUMBER()窗口函数给符合条件的艺术家按去世年份升序排名,直接取排名第一的记录:
SELECT NAME, DATA_NASCITA, DATA_MORTE FROM ( SELECT A.NAME, CONCAT_WS('/', A.BEGIN_DATE_DAY::text, A.BEGIN_DATE_MONTH::text, A.BEGIN_DATE_YEAR::text) AS DATA_NASCITA, CONCAT_WS('/', A.END_DATE_DAY::text, A.END_DATE_MONTH::text, A.END_DATE_YEAR::text) AS DATA_MORTE, -- 按去世年份-月-日升序排名,确保精准定位最早去世的那位 ROW_NUMBER() OVER (ORDER BY A.END_DATE_YEAR ASC, A.END_DATE_MONTH ASC, A.END_DATE_DAY ASC) AS rn FROM artist AS A JOIN artist_type AS AT ON A.TYPE = AT.ID WHERE AT.NAME LIKE 'Per%' AND A.END_DATE_YEAR > ( SELECT louis.END_DATE_YEAR FROM artist AS louis JOIN artist_type AS louis_at ON louis.TYPE = louis_at.ID WHERE louis_at.NAME LIKE 'Per%' AND louis.NAME = 'Louis Armstrong' ) ) ranked_artists WHERE rn = 1
如果想返回所有同年最早去世的艺术家,可以把ROW_NUMBER()换成RANK(),这样同年同月同日去世的艺术家都会被筛选出来。
小提示
原查询里用A.NAME LIKE 'Lou%'可能会匹配到其他名字以Lou开头的艺术家,建议改成精准匹配A.NAME = 'Louis Armstrong',避免出现错误结果。
内容的提问来源于stack exchange,提问作者Seniker96
相关产品推荐
相关产品推荐

