Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query to find the FIRST AND SECOND largest value from a group

i have a query like this:

SELECT
 DATEPART(year,some_date),
 DATEPART(month,some_date),
 MAX(some_value) max_value
FROM
 some_table
GROUP BY
    DATEPART(year,some_date),
    DATEPART(month,some_date)

This returns a table with: year, month, the largest value for the month.

I would like to modify the query so that i could obtain: year, month, the largest value for the month, the second largest value for the month in each row.

It seems to me that the well-known solutions like "TOP 2", "NOT IN TOP 1" or a subselect won't work here.

(To be really specific - i am using SQL Server 2008.)

like image 594
Helena Avatar asked Dec 14 '10 15:12

Helena


People also ask

How do I find the second highest value in SQL query?

Output- Now, to find the second highest salary, we nest the above query into another query as written below. SELECT MAX(SALARY) FROM Employee WHERE SALARY < (SELECT MAX(SALARY) FROM Employee); This query will give you the desired output i.e 12000, which is the second highest salary.

How do you SELECT the highest value in each group in SQL?

To find the max value of a column, use the MAX() aggregate function; it takes as its argument the name of the column for which you want to find the maximum value. If you have not specified any other columns in the SELECT clause, the maximum will be calculated for all records in the table.

How do I find the second largest number in MySQL?

MySQL has a special keyword called LIMIT which can be used to limit the result set e.g. it will allow you to see the first few rows, last few rows, or range of rows. You can use this keyword to find the second, third or Nth highest salary.

How do you find the 2nd highest in Excel?

=LARGE(A1:A5, 2) This will give you the second largest value, without any fuss. The format of the LARGE Function is =LARGE(array, k), and it picks up the Kth largest value from the array.


2 Answers

It seems to me that the question calls for a query that would return best, and second best in the same row for each month and year, like so:

month, year, best, second best
...
...

and not two rows for the same month and year containing best and second best value.

This is the solution that I came up with, so if anyone has a simpler way of achieving this, I would like to know.

with ranks as (
    select 
        year(entrydate) as [year], 
        month(entrydate) as [month], 
        views, 
        rank() over (partition by year(entrydate), month(entrydate) order by views desc) as [rank]
    from product
)
select 
    t1.year, 
    t1.month, 
    t1.views as [best], 
    t2.views as [second best]
from ranks t1
    inner join ranks t2
        on t1.year = t2.year
        and t1.month = t2.month
        and t1.rank = 1
        and t2.rank = 2

EDIT: Just out of curiosity I did a bit more testing and ended up with a simpler variation on the Stephanie Page's answer that doesn't use an aditional subquery. And I changed the rank() function to row_number() as it doesn't work when two max values are the same.

with ranks as (
    select 
        year(entrydate) as [year], 
        month(entrydate) as [month], 
        views, 
        row_number() over (partition by year(entrydate), month(entrydate) order by views desc) as [rank]
    from product
)
select 
    t1.year, 
    t1.month, 
    max(case when t1.rank = 1 then t1.views else 0 end) as [best], 
    max(case when t1.rank = 2 then t1.views else 0 end) as [second best]
from 
    ranks t1
where
    t1.rank in (1,2)
group by
    t1.year, t1.month
like image 180
skajfes Avatar answered Nov 08 '22 08:11

skajfes


RANK() is maybe the thing you are looking for...

http://msdn.microsoft.com/en-us/library/ms176102.aspx

like image 33
Yves M. Avatar answered Nov 08 '22 07:11

Yves M.