Подтвердить что ты не робот

Могу ли я выполнить max (count (*)) в SQL?

Здесь мой код:

    select yr,count(*)  from movie
join casting on casting.movieid=movie.id
join actor on casting.actorid = actor.id
where actor.name = 'John Travolta'
group by yr

Здесь вопрос

Какими были самые долгие годы для "Джона Траволты". Покажите количество фильмов, которые он сделал за каждый год.

Здесь структура таблицы:

movie(id, title, yr, score, votes, director)
actor(id, name)
casting(movieid, actorid, ord)

Это результат, который я получаю:

yr  count(*)
1976    1
1977    1
1978    1
1981    1
1994    1
etcetc

Мне нужно получить строки, для которых count(*) max.

Как это сделать?

4b9b3361

Ответ 1

Использование:

  SELECT m.yr, 
         COUNT(*) AS num_movies
    FROM MOVIE m
    JOIN CASTING c ON c.movieid = m.id
    JOIN ACTOR a ON a.id = c.actorid
                AND a.name = 'John Travolta'
GROUP BY m.yr
ORDER BY num_movies DESC, m.yr DESC

Заказ num_movies DESC будет содержать самые высокие значения в верхней части набора результатов. Если многолетний период имеет одинаковый счет, m.yr поместит последний год вверху... до следующего значения num_movies.

Могу ли я использовать MAX (COUNT (*))?


Нет, вы не можете группировать агрегированные функции друг над другом в том же предложении SELECT. Внутренний агрегат должен выполняться в подзапросе. IE:

SELECT MAX(y.num)
  FROM (SELECT COUNT(*) AS num
          FROM TABLE x) y

Ответ 2

Просто закажите count(*) desc, и вы получите наивысший результат (если вы объедините его с limit 1)

Ответ 3

SELECT * from 
(
SELECT yr as YEAR, COUNT(title) as TCOUNT
FROM actor
JOIN casting ON actor.id = casting.actorid
JOIN movie ON casting.movieid = movie.id
WHERE name = 'John Travolta'
GROUP BY yr
order by TCOUNT desc
) res
where rownum < 2

Ответ 4

с этого сайта - http://sqlzoo.net/3.htm 2 возможных решения:

с TOP 1 a ORDER BY... DESC:

SELECT yr, COUNT(title) 
FROM actor 
JOIN casting ON actor.id=actorid
JOIN movie ON movie.id=movieid
WHERE name = 'John Travolta'
GROUP BY yr
HAVING count(title)=(SELECT TOP 1 COUNT(title) 
FROM casting 
JOIN movie ON movieid=movie.id 
JOIN actor ON actor.id=actorid
WHERE name='John Travolta'
GROUP BY yr
ORDER BY count(title) desc)

с MAX:

SELECT yr, COUNT(title) 
FROM actor  
JOIN casting ON actor.id=actorid    
JOIN movie ON movie.id=movieid
WHERE name = 'John Travolta'
GROUP BY yr
HAVING 
    count(title)=
        (SELECT MAX(A.CNT) 
            FROM (SELECT COUNT(title) AS CNT FROM actor 
                JOIN casting ON actor.id=actorid
                JOIN movie ON movie.id=movieid
                    WHERE name = 'John Travolta'
                    GROUP BY (yr)) AS A)

Ответ 5

Использование max с лимитом даст вам только первую строку, но если есть две или более строк с одинаковым количеством максимальных фильмов, вы можете пропустить некоторые данные. Ниже приведен способ сделать это, если у вас есть функция rank().

SELECT
    total_final.yr,
    total_final.num_movies
    FROM
    ( SELECT 
        total.yr, 
        total.num_movies, 
        RANK() OVER (ORDER BY num_movies desc) rnk
        FROM (
               SELECT 
                      m.yr, 
                      COUNT(*) AS num_movies
               FROM MOVIE m
               JOIN CASTING c ON c.movieid = m.id
               JOIN ACTOR a ON a.id = c.actorid
               WHERE a.name = 'John Travolta'
               GROUP BY m.yr
             ) AS total
    ) AS total_final 
   WHERE rnk = 1

Ответ 6

Следующий код дает вам ответ. Он по существу реализует MAX (COUNT (*)), используя ALL. Преимущество состоит в том, что он использует очень простые команды и операции.

SELECT yr, COUNT(title)
FROM actor
JOIN casting ON actor.id = casting.actorid
JOIN movie ON casting.movieid = movie.id
WHERE name = 'John Travolta'
GROUP BY yr HAVING COUNT(title) >= ALL
  (SELECT COUNT(title)
   FROM actor
   JOIN casting ON actor.id = casting.actorid
   JOIN movie ON casting.movieid = movie.id
   WHERE name = 'John Travolta'
   GROUP BY yr)

Ответ 7

В зависимости от используемой базы данных...

select yr, count(*) num from ...
order by num desc

Большая часть моего опыта в Sybase, который использует какой-то другой синтаксис, чем другие БД. Но в этом случае вы назовете свой столбец count, чтобы вы могли сортировать его по убыванию. Вы можете сделать еще один шаг и ограничить результаты до первых 10 строк (чтобы найти его 10 самых загруженных лет).

Ответ 8

     select top 1 yr,count(*)  from movie
join casting on casting.movieid=movie.id
join actor on casting.actorid = actor.id
where actor.name = 'John Travolta'
group by yr order by 2 desc

Ответ 9

Этот вопрос старый, но был указан в новом вопросе на dba.SE. Я чувствую, что лучшие решения не были предоставлены, но я добавляю еще один.

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


Можно ли сделать max(count(*)) в SQL?

Чтобы ответить на вопрос в заголовке: Да, в Postgres 8.4 (выпущен 2009-07-01, перед тем, как этот вопрос был задан) или позже, вы можете добиться этого, вложив агрегированную функцию в функция окна:

SELECT c.yr, count(*) AS ct, max(count(*)) OVER () AS max_ct
FROM   actor   a
JOIN   casting c ON c.actorid = a.id
WHERE  a.name = 'John Travolta'
GROUP  BY c.yr;

Рассмотрим последовательность событий в запросе SELECT:

(возможный) недостаток: функции окна не группируют строки. Вы получаете все строки, оставшиеся после совокупного шага. Полезно в некоторых запросах, но не идеально для этого.


Чтобы получить одну строку с наивысшим счетчиком, вы можете использовать ORDER BY ct LIMIT 1 как @wolph hinted:

SELECT c.yr, count(*) AS ct
FROM   actor   a
JOIN   casting c ON c.actorid = a.id
WHERE  a.name = 'John Travolta'
GROUP  BY c.yr
ORDER  BY ct DESC
LIMIT  1;

Использование только базовых функций SQL, доступных в любой половине допустимой РСУБД - реализация LIMIT различается:

Или вы можете получить одну строку на группу с наивысшим счетчиком с помощью DISTINCT ON (только Postgres):


Ответ

Но вы просили:

... строки, для которых count (*) max.

Возможно, более одного. Наиболее элегантным решением является функция окна rank() в подзапросе. Ryan предоставил запрос, но это может быть проще (подробности в моем ответе выше):

SELECT yr, ct
FROM  (
   SELECT c.yr, count(*) AS ct, rank() OVER (ORDER BY count(*) DESC) AS rnk
   FROM   actor   a
   JOIN   casting c ON c.actorid = a.id
   WHERE  a.name = 'John Travolta'
   GROUP  BY c.yr
   ) sub
WHERE  rnk = 1;

В настоящее время все основные функции поддержки RDBMS поддерживаются. За исключением MySQL и forks (MariaDB, похоже, их реализовала наконец в версии 10.2).

Ответ 10

Благодаря последнему ответу

SELECT yr, COUNT(title)
FROM actor
JOIN casting ON actor.id = casting.actorid
JOIN movie ON casting.movieid = movie.id
WHERE name = 'John Travolta'
GROUP BY yr HAVING COUNT(title) >= ALL
  (SELECT COUNT(title)
   FROM actor
   JOIN casting ON actor.id = casting.actorid
   JOIN movie ON casting.movieid = movie.id
   WHERE name = 'John Travolta'
   GROUP BY yr)

У меня была такая же проблема, мне нужно было знать только те записи, которые их счетчик соответствует максимальному счету. (это может быть одна или несколько записей)

Мне нужно узнать больше о "ALL clause", и это именно то простое решение, которое я искал.

Ответ 11

create view sal as
select yr,count(*) as ct from
(select title,yr from movie m, actor a, casting c
where a.name='JOHN'
and a.id=c.actorid
and c.movieid=m.id)group by yr

----- СМОТРЕТЬ СМОТРЕТЬ -----

select yr from sal
where ct =(select max(ct) from sal)

Ю.Р. 2013