Welnu, u kunt algemene tabeluitdrukking gebruiken om codeduplicatie te voorkomen:
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)
of je kunt zoiets doen met vensterfunctie (niet getest, maar ik denk dat PostgreSQL dit toestaat):
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
Een andere manier om dit te doen is door rank() functie (niet getest, misschien moet u twee cte gebruiken in plaats van één):
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
bijwerken Toen ik dit antwoord heb gemaakt, was mijn belangrijkste doel om te laten zien hoe cte kan worden gebruikt om codeduplicatie te voorkomen. Over het algemeen is het beter om cte niet meer dan één keer in een query te gebruiken als het mogelijk is - de eerste query gebruikt 2 tabelscan (of index zoeken) en de tweede en derde gebruikt slechts één, dus ik moet specificeren dat het beter is om te gaan met deze vragen. Hoe dan ook, @Erwin maakte deze tests in zijn antwoord. Om toe te voegen aan zijn grote hoofdpunten:
- Ik raad
natural join
vanwege het foutgevoelige karakter hiervan. Eigenlijk is mijn belangrijkste RDBMS SQL Server, die het niet ondersteunt, dus ik ben meer gewend aan explicieteouter/inner join
. - Het is een goede gewoonte om altijd aliassen te gebruiken in uw zoekopdrachten, zodat u vreemde resultaten .
- Dit kan geheel subjectief zijn, maar meestal als ik een tabel alleen gebruik om rijen uit de hoofdtabel van de query te filteren (zoals in deze query, willen we gewoon
awards
ontvangen voor het jaar 2012 en filter gewoon rijen vanawardwinner
), gebruik ik liever geenjoin
, maar gebruikexists
ofin
in plaats daarvan lijkt het mij logischer.
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