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àngouter/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ụngjoin
, nhưng sử dụngexists
hoặcin
thay vào đó, nó có vẻ hợp lý hơn đối với tôi.
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