2014-01-25 1 views
0

Вот схема:Попадая кортежи SQL, которые содержат наибольшее значение совокупного атрибута после группировки

ACTOR (id, name) 
PLAY (id, name, year) 
CASTS (pid, aid, character) 

Возникает вопрос: Найти пьесы с наибольшим броском (актеры различных) и вернуть названия и литой размер этих пьес.

Это запрос SQL, что я до сих пор:

select mm.id, mm.name, count(distinct a.id) as numOfActors 
from actor a 
join casts c on c.pid = a.id 
join play mm on mm.id = c.aid 
group by mm.id, mm.name; 

Каждый кортеж вернулся из этого запроса содержит различные игры, показывая его идентификатор, имя и количество отливок имеет. Но оттуда я с трудом пытаюсь подгонять его как подзапрос в внешнем запросе, который позволит мне извлекать только кортежи с наибольшим значением numofActors (так что, если наибольшее значение равно 100, то единственные кортежи, которые будут возвращены все 100 участников).

Да, это один из тех проблем, связанных с «домашним заданием», но я также ищу концептуальное понимание (по существу, извлечение кортежей, содержащих наибольшее значение определенного агрегированного атрибута после группировки). Сортировка по убыванию и выбор верхнего кортежа не работает, так как может быть более одного кортежа с наибольшим значением.

+1

Какую базу данных вы используете? –

+0

Я использую SQL Server – ShadowCrossZero

ответ

1

Вот подход в SQL Server:

select acp.* 
from (select p.id, p.name, count(distinct a.id) as numOfActors, 
      max(count(distinct a.id)) over() as maxcnt 
     from actor a join 
      casts c 
      on c.pid = a.id join 
      play p 
      on p.id = c.aid 
     group by p.id, p.name 
    ) acp 
where numOfActors = maxnt; 

Выражение max(count(distinct a.id)) over (partition by partition by p.id) является примером оконной функции. Он вычисляет максимальное значение поля над группой строк. Поскольку () пуст (нет предложения partition by), это присваивает такое же максимальное значение новому столбцу во всех строках.

Какая ценность? Это максимум расчетного значения count(distinct a.id)) over (partition by partition by p.id). Вы хотите найти все пьесы с таким количеством участников, поэтому внешний запрос просто выбирает их.

Подзапрос необходим, потому что вы не можете использовать функции окна в предложении where.

EDIT:

with acp as (
     select p.id, p.name, count(distinct a.id) as numOfActors 
     from actor a join 
      casts c 
      on c.pid = a.id join 
      play p 
      on p.id = c.aid 
     group by p.id, p.name 
    ) 
select acp.* 
from acp join 
    (select p.id, max(numOfActors) as maxnoa 
     from acp 
     group by p.id 
    ) acpm 
    on acp.id = acpm.id and acp.numOfActors = acpm.maxnoa; 
+0

Было бы возможно без использования over()? – ShadowCrossZero

+0

Да, но для этого потребуется подзапрос, соединенный обратно с вашим выражением или общим выражением таблицы. Это самый простой и наиболее эффективный способ написания запроса. –

+0

Могли бы вы показать мне версию non-over()? – ShadowCrossZero

Смежные вопросы