PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Tìm phim có số lượng giải thưởng cao nhất trong năm nhất định - trùng lặp mã

Bạn có thể sử dụng biểu thức bảng phổ biến để tránh trùng lặp mã:

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)

hoặc bạn có thể làm điều gì đó tương tự với chức năng cửa sổ (chưa được kiểm tra, nhưng tôi nghĩ PostgreSQL cho phép điều này):

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

Một cách khác để làm điều này có thể là sử dụng rank () hàm (chưa được kiểm tra, có thể bạn phải sử dụng hai cte thay vì một):

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

cập nhật Khi tôi tạo câu trả lời này, mục tiêu chính của tôi là chỉ ra cách sử dụng cte để tránh trùng lặp mã. Nói chung, tốt hơn là tránh sử dụng cte nhiều lần trong truy vấn nếu có thể - truy vấn đầu tiên sử dụng 2 bảng quét (hoặc tìm kiếm chỉ mục) và truy vấn thứ hai và thứ ba chỉ sử dụng một, vì vậy tôi nên chỉ định rằng tốt hơn nên sử dụng các truy vấn này. Dù sao, @Erwin đã thực hiện kiểm tra này trong câu trả lời của mình. Chỉ để thêm vào những điểm chính tuyệt vời của anh ấy:

  • Tôi cũng đưa ra lời khuyên chống lại natural join vì tính chất dễ xảy ra lỗi của điều này. Trên thực tế, RDBMS chính của tôi là SQL Server không hỗ trợ nó vì vậy tôi được sử dụng nhiều hơn để rõ ràng outer/inner join .
  • Một thói quen tốt là luôn sử dụng bí danh trong các truy vấn của bạn, vì vậy bạn có thể tránh kết quả lạ .
  • Đây có thể là điều hoàn toàn chủ quan, nhưng thông thường nếu tôi đang sử dụng một số bảng chỉ để lọc ra các hàng từ bảng chính của truy vấn (giống như trong truy vấn này, chúng tôi chỉ muốn nhận được awards cho năm 2012 và chỉ lọc các hàng từ awardwinner ), Tôi không muốn sử dụng join , nhưng sử dụng exists hoặc in thay vào đó, nó có vẻ hợp lý hơn đối với tôi.
Vì vậy, truy vấn cuối cùng có thể là:
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. Postgres Kiểm tra xem IP (inet) có nằm trong danh sách Dải IP không

  2. Tạo mô-đun mới bằng PostgreSQL Tạo tiện ích mở rộng

  3. Thu thập các tập hợp thống kê lớn với pg_stat_statements?

  4. Cách tạo cơ sở dữ liệu PostgreSQL

  5. Tôi có thể đặt (trong dbase) giới hạn kích thước trên trường bytea trong PostgreSQL không?