Bueno, puedes usar expresión de tabla común para evitar la duplicación de código:
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)
o puede hacer algo como esto con función de ventana (no probado, pero creo que PostgreSQL lo permite):
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
Otra forma de hacer esto podría ser usar rank() función (no probada, puede ser que tenga que usar dos cte en lugar de uno):
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
actualizar Cuando creé esta respuesta, mi objetivo principal era mostrar cómo usar cte para evitar la duplicación de código. En general, es mejor evitar usar cte más de una vez en la consulta si es posible:la primera consulta usa 2 tablas de escaneo (o búsqueda de índice) y la segunda y la tercera usan solo una, por lo que debo especificar que es mejor ir con estas consultas. De todos modos, @Erwin hizo estas pruebas en su respuesta. Solo para agregar a sus grandes puntos principales:
- También desaconsejo la
natural join
debido a la naturaleza propensa a errores de esto. En realidad, mi RDBMS principal es SQL Server, que no lo admite, por lo que estoy más acostumbrado aouter/inner join
explícita. . - Es un buen hábito usar siempre alias en sus consultas, para que pueda evitar resultados extraños .
- Esto podría ser algo totalmente subjetivo, pero por lo general, si estoy usando una tabla solo para filtrar las filas de la tabla principal de la consulta (como en esta consulta, solo queremos obtener
awards
para el año 2012 y solo filtre las filas deawardwinner
), prefiero no usarjoin
, pero el usoexists
oin
en cambio, me parece más lógico.
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