我可以在SQL中执行max(count(*))吗?


76

这是我的代码:

    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(*)最大的行。

我该怎么做呢?


1
该问题未能公开RDBMS和版本。答案很大程度上取决于它。
Erwin Brandstetter,2016年

最聪明(可能是最快的答案,带有子查询)在这里LIMIT 1用于避免子查询。
kaiser

Answers:


95

采用:

  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

3
是的,您可以使用MAX(COUNT(*)),但是在Oracle中。techonthenet.com/sql/max.php
Andrejs,

1
@OMG Ponies-这个答案非常好-您提供的第一个SQL确实可以工作(obvs),但是您提供的第二个SQL非常优雅,并且使我也可以更好地理解子查询!谢谢您为提供全面的答案而烦恼。我试图实现这一目标-但同时也加入了分组依据-做到这一点使之成为可能!
基尔塔南

1
只是为了进一步理解这一点-您将如何使用第二个查询来获得电影数量最多的年份?现在,它可以确定一年中发生的电影数量最多的电影-但是不会给出那一年。我很想了解如何从子查询中传回第二个值,该值是与MAX结果相关的Group By值
kiltannen

28

只需订购即可count(*) desc,您将获得最高的价格(如果将其与结合使用limit 1


7
现在,如果我有几行具有最大值,并且想要显示所有具有“最大值”的值,该怎么办
Adam

@WhyCry:不能完全确定您要问的是什么,但是如果您在Stackoverflow上找不到答案,则应该将其作为一个单独的问题来问:)
Wolph 2015年

@Wolph hes说您可以有多个具有相同最大值的行,但限制为1,您看不到
urSus

重新阅读该评论(3岁)后,我认为他在寻找HAVING MAX(...) = ...
Wolph '18

7
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

子查询中不带LIMIT / TOP的ORDER BY无效。
philipxy

5

这个问题很旧,但是在dba.SE的一个新问题中引用。我觉得还没有提供最好的解决方案,所以我要添加另一个解决方案。

首先,假设参照完整性(通常与外键约束强制)你不需要加入到表在所有。这是您查询中的固定费用。到目前为止,所有答案都没有指出这一点。movie


我可以用max(count(*))SQL做吗?

要回答标题中的问题:,在Postgres 8.4(在发布此问题之前,于2009-07-01发布)中或更高版本中,您可以通过将聚合函数嵌套在window函数中来实现

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暗示

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;

仅使用任何中途的RDBMS中可用的基本SQL功能-LIMIT实现有所不同:

或者,您可以使用(仅Postgres)在每个组中获得最高计数的一行DISTINCT ON


回答

但您要求:

... count(*)最大的行

可能不止一个。最优雅的解决方案是在子查询中使用window函数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版中实现了它们)。


[...您根本不需要加入桌面电影]。必须连接表'movie',因为这是唯一带有'yr'列(电影年份)的表。
凯文·斯旺

4

它来自此网站-http : //sqlzoo.net/3.htm 2种可能的解决方案:

与TOP 1一个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)

3

将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

3

以下代码为您提供了答案。它本质上通过使用ALL实现MAX(COUNT(*))。它具有使用非常基本的命令和操作的优点。

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)

2

根据您使用的数据库...

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

我的大部分经验是在Sybase中使用的,该语法与其他数据库使用的语法有所不同。但是在这种情况下,您要命名计数列,以便可以对其进行降序排列。您可以走得更远,并将结果限制在前10行(以查找他最忙的10年)。


2

多亏了最后一个答案

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子句”的更多信息,而这正是我一直在寻找的简单解决方案。


1
     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

1
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年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.