Můžete použít běžný tabulkový výraz abyste zabránili duplicitě kódu:
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)
nebo můžete něco takového udělat pomocí funkce okna (netestováno, ale myslím, že PostgreSQL to umožňuje):
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
Dalším způsobem, jak toho dosáhnout, může být použití rank() funkce (netestováno, možná budete muset použít dvě cte místo jednoho):
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
aktualizovat Když jsem vytvořil tuto odpověď, mým hlavním cílem bylo ukázat, jak používat cte, aby se zabránilo duplicitě kódu. Obecně je lepší vyhnout se použití cte více než jednou v dotazu, pokud je to možné - první dotaz používá 2 skenování tabulky (nebo hledání indexu) a druhý a třetí používá pouze jeden, takže bych měl uvést, že je lepší jít s tyto dotazy. Každopádně @Erwin provedl tyto testy ve své odpovědi. Jen abych dodal k jeho velkým hlavním bodům:
- Také nedoporučuji
natural join
z důvodu náchylnosti k chybám. Ve skutečnosti je mým hlavním RDBMS SQL Server, který jej nepodporuje, takže jsem více zvyklý na explicitníouter/inner join
. - Je dobrým zvykem ve svých dotazech vždy používat aliasy, takže se můžete vyhnout podivné výsledky .
- To může být zcela subjektivní záležitost, ale obvykle, pokud nějakou tabulku používám pouze k odfiltrování řádků z hlavní tabulky dotazu (jako v tomto dotazu, chceme jen získat
awards
pro rok 2012 a stačí filtrovat řádky odawardwinner
), raději nepoužívámjoin
, ale použijteexists
neboin
místo toho mi to připadá logičtější.
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