Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 查询以从组中查找第一个和第二个最大值_Sql_Sql Server 2008 - Fatal编程技术网

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

Sql 查询以从组中查找第一个和第二个最大值,sql,sql-server-2008,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) 这将返回一个表,其中包含:年、月、该月的最大值 我想修改查询,以便获得: 年,月,该月的最大值,每行中该月的第二大值 在我看来,

我有这样一个问题:

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、而不是TOP 1或subselect这样的著名解决方案在这里不起作用


具体地说,我使用的是SQL Server 2008。

这有点老套,但如果使用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
这将为您提供两个月值最高的行,添加的子选择将为您提供每个分组的最大值

排名也许是你要找的东西


嗯,这是一种装备,但你可以通过子查询来实现。。。我不使用这个最大值,而是选择一些年和月匹配的值,行数分别为1/行数=2,并按某个值排序


无法像在SQLite中那样使用偏移/限制是我对SQL Server的一个不喜欢的地方。

您可以在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
这将对数据进行分区,即按月/年对数据进行分组,在每个组中先按某个最大值降序排序,然后您可以从该CTE中选择每个组的前两个


RANK也能工作。我最常使用ROW_NUMBER——虽然它产生的结果略有不同——这取决于您的需要。

在我看来,这个问题需要一个查询,该查询将在同一行中每个月和每年返回最佳结果和次优结果,如下所示:

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
编辑:出于好奇,我做了更多的测试,最后在上得到了一个更简单的变体,它不使用传统的子查询。我将rank函数改为row_number,因为当两个max值相同时,它不起作用

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

要在没有连接的情况下执行此操作,我将显示Oracle。。。您将只使用用例而不是解码

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]

他想要最大值和倒数第二个最大值。@Stephanie:请查看我的更新。我花了几次阅读这篇文章的时间才弄明白那个部分。幸运的是,我能够改变它back@Stephanie:非常感谢。不过,对一些老派的SQL不赞成吗?我和任何数据极客一样,都是CTE和所有SQL Server 2005+产品的忠实粉丝,但我认为我的解决方案有一些优点,比如:可移植性/适用于其他系统只是必须修改最重要的关键字,对于非Sql Server人员等更明确的意图。底线是,对一个有趣问题的普通解决方案,尽管没有那么令人兴奋,但可能会引起更广泛的兴趣。您如何使用rank获得期望的结果?@skajfes:请参阅我的回答,并用rank替换ROW_编号:-Sql Server 2011将有偏移量和限制-请参阅@marc_s:最后,如果你问我是的,这肯定是一个有效的解决方案,太迟了十年。我认为有几种使用连接的类似解决方案,但我仍然想知道或者更好地说,只是好奇是否有一个没有连接的解决方案?多年来,我遇到过类似的问题,也想知道是否有一个没有连接的更简单的解决方案,但不能很好地解决。正如结果所示,加入解决方案虽然看起来像是一个乱七八糟的问题,但它可以完美且快速地工作。@Helena:btw投票并/或接受答案,如果您认为它有用,欢迎使用stackoverflowBtw。您的解决方案有一个小问题:如果第一个和第二个最高值在一个月内相同,那么相应的行根本不会出现在结果集中。这是因为在这种情况下不存在秩2-秩是,例如,1,1,3,4,。。。使用ROW_NUMBER而不是RANK似乎可以解决这个问题。@Helena:你是对的,我在想当两个值相同时会发生什么,但在测试时我忘记了-是的,听起来ROW_NUMBER应该解决这个问题。这两个值都给了你,但不在同一行。@Stephanie Page:我不认为这是一个要求-但是的,这是真的-它将分别列出前两个值,每个值都在单独的数据行中