tags:

views:

42

answers:

2

What I am trying to achieve is to get the rows having the maximum value from a table of the following form:

A | B | Ratio 
0 | 1 | 1.0
1 | 2 | 1.0
2 | 3 | 1.0
3 | 4 | 0.33
4 | 5 | 0.25

I am trying to display only rows containing the maximum value (in this case 1.0). May be I am not doing this right. I have a query of the form:

SELECT A,B,C 
FROM (---Long Sub Query--- Aliased as Full_Table)
WHERE RATIO=(SELECT MAX(RATIO) FROM Full_Table);

But Full_Table cannot be referenced from the second sub-query. There are some rows having the same maximum value which is the reason I was using this query. Is there a better construct to achieve this? In the worst case, I have to replace the second Full_Table by the entire long query but I'm hoping there is a better way to do this.

+5  A: 

You can use a Common Table Expression:

WITH Full_Table AS (---Long Sub Query---)
SELECT A,B,C 
FROM Full_Table
WHERE RATIO=(SELECT MAX(RATIO) FROM Full_Table);
Mark Byers
@Mark: Beautiful..! Thank you very much :)
Legend
+1  A: 

Use:

SELECT full_table.a,
       full_table.b,
       full_table.c
  FROM (SELECT ...,
               RANK() OVER (ORDER BY ratio DESC) AS rank
          FROM Sub Query---) full_table
 WHERE full_table.rank = 1

It's not clear if there can be more than one record returned, so I used RANK() rather than ROW_NUMBER() because ROW_NUMBER would only return one record.

You could incorporate that into a WITH clause, but it's still one pass over the derived table/inline view vs your two passes...

Oracle 9i+ supports the WITH syntax, calling it "Subquery Factoring". Those coming from SQL Server 2005+ know the WITH syntax as a Common Table Expression (CTE). Unlike SQL Server's implementation, the WITH syntax on Oracle 9i - 11g is not recursive - Oracle only added recursive WITH support (now that it's ANSI) in 11g R2, in part due to Oracle supporting recursive functionality with the CONNECT BY syntax (supported since Oracle v2). WITH syntax is syntactic sugar for derived tables/inline views - the query plan isn't reused for each instance.

WITH full_table AS (
  SELECT...)
SELECT x.a, x.b, x.c
  FROM full_table x
  JOIN (SELECT MAX(t.ratio) AS max_ratio 
          FROM full_table t) y ON y.max_ratio = x.ratio

...is the identical to using:

SELECT x.a, x.b, x.c
  FROM (SELECT ...) x
  JOIN (SELECT MAX(t.ratio) AS max_ratio 
          FROM (SELECT ...) t) y ON y.max_ratio = x.ratio
OMG Ponies