Nun, Sie können den allgemeinen Tabellenausdruck verwenden Codeduplizierung zu vermeiden:
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)
oder Sie können so etwas mit der Fensterfunktion machen (ungetestet, aber ich denke, PostgreSQL erlaubt dies):
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
Eine andere Möglichkeit, dies zu tun, könnte die Verwendung von rank() Funktion (ungetestet, möglicherweise müssen Sie zwei cte anstelle von einem verwenden):
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
aktualisieren Als ich diese Antwort erstellt habe, war mein Hauptziel zu zeigen, wie man cte verwendet, um Codeduplizierung zu vermeiden. Im Allgemeinen ist es besser zu vermeiden, cte mehr als einmal in Abfragen zu verwenden, wenn dies möglich ist - die erste Abfrage verwendet 2 Tabellenscans (oder Indexsuchen) und die zweite und dritte verwendet nur eine, daher sollte ich angeben, dass es besser ist, mit zu gehen diese Abfragen. Wie auch immer, @Erwin hat diese Tests in seiner Antwort durchgeführt. Nur um seine großen Hauptpunkte hinzuzufügen:
- Ich rate auch von
natural join
ab aufgrund der Fehleranfälligkeit dieser. Eigentlich ist mein Haupt-RDBMS SQL Server, die es nicht unterstützen, also bin ich eher an expliziteouter/inner join
gewöhnt . - Es ist eine gute Angewohnheit, in Ihren Abfragen immer Aliase zu verwenden, damit Sie seltsame Ergebnisse .
- Dies könnte eine völlig subjektive Sache sein, aber normalerweise, wenn ich eine Tabelle nur verwende, um Zeilen aus der Haupttabelle der Abfrage herauszufiltern (wie in dieser Abfrage, wollen wir nur
awards
erhalten für das Jahr 2012 und filtern Sie einfach die Zeilen vonawardwinner
), ziehe ich es vor,join
nicht zu verwenden , aber verwenden Sieexists
oderin
stattdessen erscheint es mir logischer.
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