我试图写一个查询(PostgreSQL),以获得“2012年获奖最多的电影”。
我有以下表格:
CREATE TABLE Award(
ID_AWARD bigserial CONSTRAINT Award_pk PRIMARY KEY,
award_name VARCHAR(90),
category VARCHAR(90),
award_year integer,
CONSTRAINT award_unique UNIQUE (award_name, category, award_year));
CREATE TABLE AwardWinner(
ID_AWARD integer,
ID_ACTOR integer,
ID_MOVIE integer,
CONSTRAINT AwardWinner_pk PRIMARY KEY (ID_AWARD));
字符串
我写了下面的查询,它给出了正确的结果,但我认为有相当多的代码重复。
select * from
(select id_movie, count(id_movie) as awards
from Award natural join awardwinner
where award_year = 2012 group by id_movie) as SUB
where awards = (select max(count) from
(select id_movie, count(id_movie)
from Award natural join awardwinner
where award_year = 2012 group by id_movie) as SUB2);
型
所以SUB
和SUB2
是完全相同的子查询。有更好的方法吗?
3条答案
按热度按时间qzlgjiam1#
你可以使用common table expression来避免代码重复:
字符串
或者你可以用window function做类似的事情(未经测试,但我认为PostgreSQL允许这样做):
型
另一种方法是使用rank()函数(未经测试,可能需要使用两个cte而不是一个):
型
update当我创建这个答案时,我的主要目标是展示如何使用cte来避免代码重复。一般来说,如果可能的话,最好避免在查询中多次使用cte-第一个查询使用2个表扫描(或索引查找),第二个和第三个只使用一个,所以我应该指定最好使用这些查询。无论如何,@靳泽在回答中做了这样的测试,只是为了补充他的一大优点:
natural join
,因为它容易出错。实际上,我的主要RDBMS是SQL Server,它不支持它,所以我更习惯于显式的outer/inner join
。awards
,只过滤awardwinner
中的行),我宁愿不使用join
,而是使用exists
或in
,这对我来说似乎更合乎逻辑。因此,最终查询可能是:
xqkwcwgp2#
获取所有获奖影片
字符串
要点
EXPLAIN ANALYZE
测试。型
NATURAL JOIN
,如果您稍后更改/向底层表添加列,则很容易损坏。使用
USING
的JOIN条件几乎一样短,但不容易中断。id_movie
不能为NULL(被JOIN条件排除,也是pk的一部分),因此使用count(*)
更短,速度也更快。结果相同。就一部电影
更短,更快,然而,如果你只需要 * 一个 * 赢家:
型
这里使用位置参考(
1
,2
)作为简写。我在
ORDER BY
中添加了id_movie
作为决胜局,以防多部电影都有资格获胜。b4qexyjb3#
你不需要这样的东西吗?
字符串
或者可能(取决于你在寻找什么):
型