PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Намерете филми с най-голям брой награди през определена година - дублиране на код

Е, можете да използвате израз на обща таблица за да избегнете дублиране на код:

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Проблем с разпределението на седмичния час в Rails и Postgresql

  2. PostgreSQL date() с часова зона

  3. Кой е най-бързият начин за извличане на последователни данни от база данни?

  4. Django нулира полето за автоматично нарастване на pk/id за производство

  5. PostgreSQL - групиране по jsonb колона