Anda dapat menggunakan ekspresi tabel umum untuk menghindari duplikasi kode:
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)
atau Anda dapat melakukan sesuatu seperti ini dengan fungsi jendela (belum diuji, tapi saya pikir PostgreSQL mengizinkan ini):
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
Cara lain untuk melakukannya adalah dengan menggunakan rank() fungsi (belum diuji, mungkin Anda harus menggunakan dua cte alih-alih satu):
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
perbarui Ketika saya membuat jawaban ini, tujuan utama saya adalah menunjukkan cara menggunakan cte untuk menghindari duplikasi kode. Secara umum, lebih baik menghindari penggunaan cte lebih dari satu kali dalam kueri jika memungkinkan - kueri pertama menggunakan 2 pemindaian tabel (atau pencarian indeks) dan kedua dan ketiga hanya menggunakan satu, jadi saya harus menentukan bahwa itu lebih baik untuk digunakan pertanyaan-pertanyaan ini. Bagaimanapun, @Erwin membuat tes ini dalam jawabannya. Hanya untuk menambah poin utamanya yang hebat:
- Saya juga menyarankan agar tidak
natural join
karena sifat rawan kesalahan ini. Sebenarnya RDBMS utama saya adalah SQL Server yang tidak mendukungnya jadi saya lebih terbiasa denganouter/inner join
eksplisit . - Adalah kebiasaan yang baik untuk selalu menggunakan alias dalam kueri Anda, sehingga Anda dapat menghindari hasil aneh .
- Ini bisa menjadi hal yang sangat subjektif, tetapi biasanya jika saya menggunakan beberapa tabel hanya untuk memfilter baris dari tabel utama kueri (seperti dalam kueri ini, kami hanya ingin mendapatkan
awards
untuk tahun 2012 dan cukup filter baris dariawardwinner
), saya lebih suka untuk tidak menggunakanjoin
, tetapi gunakanexists
atauin
sebaliknya, tampaknya lebih logis bagi saya.
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