我有这样的查询:
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)
这将返回一个表格,其中包含:年,月,该月份的最大值。
我想修改查询,以便我可以获得: 年,月,本月最大值,每月第二大值 。
在我看来,众所周知的解决方案,如“TOP 2”,“NOT IN TOP IN”或subselect将不适用于此。
(非常具体 - 我正在使用SQL Server 2008.)
感谢任何帮助,thx。
答案 0 :(得分:3)
RANK()
可能是您正在寻找的东西......
答案 1 :(得分:3)
在我看来,这个问题需要一个最佳的查询,并且每个月和每年在同一行中排名第二,如下所示:
month, year, best, second best
...
...
而不是包含最佳和第二最佳值的同一个月和每年的两行。
这是我提出的解决方案,所以如果有人有更简单的方法来实现这一点,我想知道。
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
编辑:出于好奇,我做了一些测试,最后在Stephanie Page's answer上使用了一个更简单的变体而没有使用aditional子查询。我将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
答案 2 :(得分:2)
在没有连接的情况下执行此操作(我将显示Oracle ...您将只使用CASE而不是DECODES)
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 [year], [month], Max([best]), Max([second best])
FROM
( select
t1.year,
t1.month,
Decode([rank],1,t1.views,0) as [best],
Decode([rank],2,t1.views,0) as [second best]
from ranks t1
where t1.rank <= 2 ) x
GROUP BY [year], [month]
答案 3 :(得分:1)
这是一个老派,但如果你使用ORDER BY,TOP和子查询将会起作用。试试这个:
SELECT TOP 2
DATEPART(year,some_date),
DATEPART(month,some_date),
(SELECT MAX(st1.some_value) FROM some_table AS st1
WHERE DATEPART(month,some_date) = DATEPART(month,st1.some_date)) AS max_value
FROM
some_table
GROUP BY
DATEPART(year,some_date),
DATEPART(month,some_date)
ORDER BY DATEPART(month,some_date) DESC
这将为您提供两行&#34;最高&#34;月份值和添加的子选择应该为每个分组提供最大值。
答案 4 :(得分:1)
您可以在SQL Server 2005及更高版本中使用具有排名功能的CTE:
;WITH TopValues AS
(
SELECT
YEAR(some_date) AS 'Year',
MONTH(some_date) AS 'Month',
Some_Value,
ROW_NUMBER() OVER(PARTITION BY YEAR(some_date),MONTH(some_date)
ORDER BY Some_Value DESC) AS 'RowNumber'
FROM
dbo.some_table
)
SELECT
Year, Month, Some_Value
FROM
TopValues
WHERE
RowNumber <= 2
这将按月/年“分区”(即分组)您的数据,在每个组内按Some_Value
降序排序(最大的第一个),然后您可以从该CTE中选择每组中的前两个。
RANK()
同样适用(我经常使用ROW_NUMBER
) - 它会产生稍微不同的结果 - 但实际上取决于您的需求。
答案 5 :(得分:0)
嗯,这是一种装备,但是你可以用子查询做到这一点......而不是使用那个max我会选择具有匹配年份和年份的some_values。 month,row_number()= 1 / row_number()= 2,并按some_value DESC排序。
无法在SQLite中使用OFFSET / LIMIT,这是我对SQL Server的不喜欢。