Е, можете да използвате израз на обща таблица за да избегнете дублиране на код:
with cte_s as (
select id_movie, count(id_movie) as awards
from Award natural join awardwinner
where award_year = 2012
group by id_movie
)
select
sub.id_movie, sub.awards
from cte_s as sub
where sub.awards = (select max(sub2.awards) from cte_s as sub2)
или можете да направите нещо подобно с прозоречна функция (непроверено, но мисля, че PostgreSQL позволява това):
with cte_s as (
select
id_movie,
count(id_movie) as awards,
max(count(id_movie)) over() as max_awards
from Award natural join awardwinner
where award_year = 2012
group by id_movie
)
select id_movie
from cte_s
where max_awards = awards
Друг начин да направите това може да бъде да използвате rank() функция (непроверено, може да се наложи да използвате два cte вместо един):
with cte_s as (
select
id_movie,
count(id_movie) as awards,
rank() over(order by count(id_movie) desc) as rnk
from Award natural join awardwinner
where award_year = 2012
group by id_movie
)
select id_movie
from cte_s
where rnk = 1
актуализация Когато създадох този отговор, основната ми цел беше да покажа как да използвам cte, за да избегна дублиране на код. Като цяло е по-добре да избягвате използването на cte повече от един път в заявка, ако е възможно - първата заявка използва сканиране на 2 таблици (или търсене на индекс), а втората и третата използват само едно, така че трябва да уточня, че е по-добре да отидете с тези запитвания. Както и да е, @Erwin направи тези тестове в своя отговор. Само да добавя към страхотните си основни точки:
- Също така съветвам срещу
natural join
поради склонния към грешки характер на това. Всъщност основната ми RDBMS е SQL Server, който не го поддържа, така че съм свикнал повече с изричноouter/inner join
. - Добър навик е винаги да използвате псевдоними във вашите заявки, така че можете да избегнете странни резултати .
- Това може да е напълно субективно нещо, но обикновено, ако използвам някаква таблица само за филтриране на редове от основната таблица на заявката (като в тази заявка, ние просто искаме да получим
awards
за 2012 г. и просто филтрирайте редове отawardwinner
), предпочитам да не използвамjoin
, но използвайтеexists
илиin
вместо това изглежда по-логично за мен.
with cte_s as (
select
aw.id_movie,
count(*) as awards,
rank() over(order by count(*) desc) as rnk
from awardwinner as aw
where
exists (
select *
from award as a
where a.id_award = aw.id_award and a.award_year = 2012
)
group by aw.id_movie
)
select id_movie
from cte_s
where rnk = 1