Varun Rao
Varun Rao

Reputation: 801

How to get other columns with are not in GROUP BY clause in a oracle select sql?

I have a table MOVIE containing this data.

MOVIE_ID  MOVIE_TITLE              CATEGORY        SALES_AMT
--------- ------------------------ --------------- ----------
M_0000004 The Boss Baby            Animation       2000
M_0000006 Star Wars: The Last Jedi Science Fiction 3000
M_0000007 Get Out                  Horror          4000
M_0000008 Million Dollar Arm       Action          2000
M_0000009 The Conjuring            Horror          1000
M_0000012 The Dark Knight          Action          3000

I need the Top movies data based on SALES_AMT with respect to CATEGORY

The required result is this:

MOVIE_ID  MOVIE_TITLE              CATEGORY        SALES_AMT
--------- ------------------------ --------------- ----------
M_0000004 The Boss Baby            Animation       2000
M_0000006 Star Wars: The Last Jedi Science Fiction 3000
M_0000007 Get Out                  Horror          4000
M_0000012 The Dark Knight          Action          3000

If I use GROUP_BY option, I cannot select MOVIE_ID and MOVIE_TITLE

select CATEGORY, MAX(SALES_AMT)
from MOVIE
group by CATEGORY
;

Upvotes: 2

Views: 4324

Answers (3)

Connor McDonald
Connor McDonald

Reputation: 11591

Let's say you run this first:

SQL> select deptno, min(sal)
  2  from emp
  3  group by deptno;

and then want to get the employee who has that minimum salary. Then this of course fails:

SQL> select deptno, empno, min(sal)
  2  from emp
  3  group by deptno;

ORA-00979: not a GROUP BY expression

But you can use the KEEP syntax with a window function to assist

SQL> select deptno, min(sal), min(empno) 
  2    KEEP ( dense_rank FIRST order by sal) empno
  3  from emp
  4  group by deptno
  5  /

    DEPTNO   MIN(SAL)      EMPNO
---------- ---------- ----------
        10       1300       7934
        20        800       7369
        30        950       7900

where this is read as "EMPNO 7934 is the person who has the salary of 1300"

Upvotes: 0

Chris Mack
Chris Mack

Reputation: 5208

You can use RANK() to achieve this:

SELECT
    MOVIE_ID
    , MOVIE_TITLE
    , CATEGORY
    , SALES_AMT
FROM
    (
        SELECT
            MOVIE_ID
            , MOVIE_TITLE
            , CATEGORY
            , SALES_AMT
            , RANK() OVER (PARTITION BY CATEGORY ORDER BY SALES_AMT DESC) RNK
        FROM MOVIE
    ) Q
WHERE RNK = 1

This would be if you wanted to see duplicates in your results (where sales amounts were equal), otherwise, replace RANK with ROW_NUMBER.

Upvotes: 0

Kacper
Kacper

Reputation: 4818

Try with analytic functions and subquery

select movie_id, movie_title, category, sales_amt 
from (
  select movie_id, movie_title, category, sales_amt, 
  row_number() over (partition by category order by sales_amt desc) r 
  from movie
) where r = 1

Upvotes: 5

Related Questions