Intellipaat Back

Explore Courses Blog Tutorials Interview Questions
0 votes
4 views
in SQL by (20.3k points)

I have a big problem with an SQL Statement in Oracle. I want to select the TOP 10 Records ordered by STORAGE_DB which aren't in a list from another select statement.

This one works fine for all records:

SELECT DISTINCT 

  APP_ID, 

  NAME, 

  STORAGE_GB, 

  HISTORY_CREATED, 

  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  

  FROM HISTORY WHERE 

      STORAGE_GB IS NOT NULL AND 

        APP_ID NOT IN (SELECT APP_ID

                       FROM HISTORY

                        WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

But when I am adding

AND ROWNUM <= 10

ORDER BY STORAGE_GB DESC

I'm getting some kind of "random" Records. I think because the limit takes in place before the order.

Does someone have a good solution? The other problem: This query is really slow (10k+ records)

2 Answers

0 votes
by (40.7k points)

Try to put your current query in subquery as follows :

SELECT * FROM (

  SELECT DISTINCT 

  APP_ID, 

  NAME, 

  STORAGE_GB, 

  HISTORY_CREATED, 

  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  

  FROM HISTORY WHERE 

    STORAGE_GB IS NOT NULL AND 

      APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')

  ORDER BY STORAGE_GB DESC )

WHERE ROWNUM <= 10

In Oracle, rownum is used to the result after it is returned. You just have to filter the result after it has been returned, therefore the subquery will be required. 

You could also use the RANK() function to get Top-N results. For performance, you can use NOT EXISTS in place of NOT IN.

0 votes
by (1.9k points)

SELECT * FROM (

 SELECT DISTINCT

   APP_ID,

   NAME,

   STORAGE_GB,

   HISTORY_CREATED,

   TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE 

 FROM HISTORY

 WHERE STORAGE_GB IS NOT NULL

   AND APP_ID NOT IN (

     SELECT APP_ID

     FROM HISTORY

     WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009'

   )

 ORDER BY STORAGE_GB DESC

)

WHERE ROWNUM <= 10

In Oracle, rownum is used to control the display of the data after it is selected. Hence, the main query will bring back the results for you that you can filter out later on. That's why the subquery will be necessary.

The method of ranking might also be helpful in this case to get Top-N results besides these ones include using the NOT EXISTS condition instead of NOT IN.


 

Related questions

0 votes
1 answer
0 votes
1 answer
0 votes
1 answer
asked Jul 29, 2019 in SQL by Tech4ever (20.3k points)
0 votes
1 answer

31k questions

32.8k answers

501 comments

693 users

Browse Categories

...