简体   繁体   中英

SQL Query with multiple columns and an aggregate function using GROUP BY

I am having troubles with my SQL query. I have the following movie table:

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID_MOVIE                                  NOT NULL NUMBER(4)
 TITLE                                     NOT NULL VARCHAR2(30)
 GENRE                                     NOT NULL VARCHAR2(30)
 YEAR                                      NOT NULL NUMBER(4)
 COUNTRY                                   NOT NULL VARCHAR2(30)
 DURATION                                  NOT NULL NUMBER(3)
 BUDGET                                             NUMBER(10)
 INCOMES                                            NUMBER(10)
 ID_MOVIE_PREV                                      NUMBER(4)
 ID_DIRECTOR

i tried this command: select m.genre, max(m.budget),m.title from movie m group by m.genre,m.title; and got this result:

GENRE                          MAX(M.BUDGET) TITLE
------------------------------ ------------- ------------------------------
Western                              1200000 The Good, the Bad and the Ugly
Horror                                806947 Psycho
Crime                                7000000 The Godfather: Part III
Action                             185000000 The Dark Knight
Drama                               26000000 Philadelphia
Drama                               13000000 In the Name of the Father
Action                             150000000 Batman Begins
Historical                          23800000 The Last Emperor
Science-fiction                      5800000 Planet of the Apes
Crime                                7000000 The Godfather
Action                             230000000 The Dark Knight Rises

GENRE                          MAX(M.BUDGET) TITLE
------------------------------ ------------- ------------------------------
Comedy                              28000000 Zoolander
Crime                                9000000 Pulp Fiction
Crime                               13000000 The Godfather: Part II
War                                 70000000 Saving Private Ryan
Science-fiction                     28000000 Blader Runner
Drama                               33000000 Gran Torino

I'd like to have the title of the maximum of each gender. Can anyone tell me on where is my mistake? Thank you by advance!

I suspect that your query does not actually aggregate, since you would expect that (genre, title) tuples are unique in the table.

You can use a correlated subquery to filter the table:

select genre,title, budget
from movie m
where budget = (
    select max(m1.budget)
    from movie m1
    where m1.genre = m.genre
)

This seems to me like the simplest way to phrase what you are trying to achieve. For performance, consider an index on (genre, budget) .

Here is a demo on DB Fiddle (based on the above assumption that your current resultset can be considered as your raw data):

GENRE           | TITLE                          |    BUDGET
:-------------- | :----------------------------- | --------:
Western         | The Good, the Bad and the Ugly |   1200000
Horror          | Psycho                         |    806947
Historical      | The Last Emperor               |  23800000
Action          | The Dark Knight Rises          | 230000000
Comedy          | Zoolander                      |  28000000
Crime           | The Godfather: Part II         |  13000000
War             | Saving Private Ryan            |  70000000
Science-fiction | Blader Runner                  |  28000000
Drama           | Gran Torino                    |  33000000

You can use row_number() analytic function:

select genre, budget,title
  from
  (
      select genre, budget, title,
             row_number() over (partition by genre order by budget desc) as rn       
        from movie 
   )
  where rn = 1

grouping is performed by partition by and maximum value for budget is found by ordering by descending budget.

Demo

In Oracle, you can use aggregation:

select genre,
       max(title) keep (dense_rank first order by budget desc) as title,
       max(budget) as budget
from movie m
group by genre;

The keep expression is essentially doing a get-the-first-value function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM