Can I do a max(count(*)) in SQL?

前端 未结 11 1766
遥遥无期
遥遥无期 2020-11-29 01:02

Here\'s my code:

    select yr,count(*)  from movie
join casting on casting.movieid=movie.id
join actor on casting.actorid = actor.id
where actor.name = \'Jo         


        
相关标签:
11条回答
  • 2020-11-29 01:41

    Depending on which database you're using...

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

    Most of my experience is in Sybase, which uses some different syntax than other DBs. But in this case, you're naming your count column, so you can sort it, descending order. You can go a step further, and restrict your results to the first 10 rows (to find his 10 busiest years).

    0 讨论(0)
  • 2020-11-29 01:43
    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
    
    0 讨论(0)
  • 2020-11-29 01:49

    This question is old, but was referenced in a new question on dba.SE. I feel the best solutions haven't been provided, yet, so I am adding another one.

    First off, assuming referential integrity (typically enforced with foreign key constraints) you do not need to join to the table movie at all. That's dead freight in your query. All answers so far fail to point that out.


    Can I do a max(count(*)) in SQL?

    To answer the question in the title: Yes, in Postgres 8.4 (released 2009-07-01, before this question was asked) or later you can achieve that by nesting an aggregate function in a window function:

    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;
    

    Consider the sequence of events in a SELECT query:

    • Best way to get result count before LIMIT was applied

    The (possible) downside: window functions do not aggregate rows. You get all rows left after the aggregate step. Useful in some queries, but not ideal for this one.


    To get one row with the highest count, you can use ORDER BY ct LIMIT 1 like @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;
    

    Using only basic SQL features available in any halfway decent RDBMS - the LIMIT implementation varies:

    • SQL select elements where sum of field is less than N

    Or you can get one row per group with the highest count with DISTINCT ON (only Postgres):

    • Select first row in each GROUP BY group?

    Answer

    But you asked for:

    ... rows for which count(*) is max.

    Possibly more than one. The most elegant solution is with the window function rank() in a subquery. Ryan provided a query but it can be simpler (details in my answer above):

    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;
    

    All major RDBMS support window functions nowadays. Except MySQL and forks (MariaDB seems to have implemented them at last in version 10.2).

    0 讨论(0)
  • 2020-11-29 01:49

    The following code gives you the answer. It essentially implements MAX(COUNT(*)) by using ALL. It has the advantage that it uses very basic commands and operations.

    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)
    
    0 讨论(0)
  • 2020-11-29 01:51

    Just order by count(*) desc and you'll get the highest (if you combine it with limit 1)

    0 讨论(0)
  • 2020-11-29 01:51
         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
    
    0 讨论(0)
提交回复
热议问题