sql >> Database >  >> RDS >> PostgreSQL

Vind films met het hoogste aantal onderscheidingen in een bepaald jaar - codeduplicatie

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 expliciete outer/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 van awardwinner ), gebruik ik liever geen join , maar gebruik exists of in in plaats daarvan lijkt het mij logischer.
De laatste vraag zou dus kunnen zijn:
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


  1. Het aantal totale rijen toevoegen via Marshmallow met @post_dump?

  2. Maak verbinding met SQL Server met Windows-verificatie vanaf een Linux-machine via JDBC

  3. Met behulp van PDO verhoogde uitzondering kon stuurprogramma niet vinden

  4. SQL-datumnotatie