查询以查找组中的第一个和第二个最大值

Hel*_*ena 7 sql sql-server-2008

我有这样的查询:

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)
Run Code Online (Sandbox Code Playgroud)

这将返回一个表,其中包含:year,month,该月份的最大值.

我想修改查询,以便我可以获得: 年,月,月份的最大值,每行的第二大值.

在我看来,众所周知的解决方案,如"TOP 2","不在前1"或子选择将无法在这里工作.

(具体来说 - 我正在使用SQL Server 2008.)

感谢任何帮助,thx.

ska*_*fes 5

在我看来,该问题要求的查询将在每个月和每年的同一行中返回最佳结果,并返回第二最佳结果,例如:

month, year, best, second best
...
...
Run Code Online (Sandbox Code Playgroud)

并且在同一月份和年份中没有两行包含最高和第二最高价值。

这是我想出的解决方案,因此,如果有人能以更简单的方式实现这一目标,我想知道。

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
Run Code Online (Sandbox Code Playgroud)

编辑:出于好奇,我做了一些测试,最终对斯蒂芬妮·佩奇(Stephanie Page)的答案做了一个更简单的变化,该变化不使用附加子查询。我将rank()函数更改为row_number(),因为当两个最大值相同时它不起作用。

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
Run Code Online (Sandbox Code Playgroud)