Sql 如何选择每月得分最高的ID

Sql 如何选择每月得分最高的ID,sql,sql-server,Sql,Sql Server,我对SQL相当陌生。我的桌子是空的 id mark datetimes ------|-----|------------ 1001 | 10 | 2011-12-20 1002 | 11 | 2012-01-10 1005 | 12 | 2012-01-10 1003 | 10 | 2012-01-10 1004 | 11 | 2018-10-10 1006 | 12 |

我对SQL相当陌生。我的桌子是空的

   id     mark  datetimes      
    ------|-----|------------
    1001  | 10  | 2011-12-20   
    1002  | 11  | 2012-01-10 
    1005  | 12  | 2012-01-10  
    1003  | 10  | 2012-01-10 
    1004  | 11  | 2018-10-10 
    1006  | 12  | 2018-10-19  
    1007  | 13  | 2018-03-12  
    1008  | 15  | 2018-03-13
我需要在每个月底选择一个得分最高的ID(年份也很重要),ID可以重复

我期望的输出是

    id    mark  
    -----|----
   1001  | 10
   1005  | 12
   1006  | 12
   1008  | 15
到目前为止,我每个月只能得到最高的价值

 Select Max(Mark)'HighestMark' 
 From StudentMark
 Group BY Year(datetimes), Month(datetimes)
当我试图

 Select Max(Mark)'HighestMark', ID 
 From StudentMark
 Group BY Year(datetimes), Month(datetimes), ID
我明白了

Id          HighestMark
----------- ------------
1001        10
1002        11
1003        12
1004        10
1005        11
1006        12
1007        13
1008        15

我看不到一个查询就可以做到这一点。但是我们可以很容易地使用一个子查询来查找每个学生当月的最终分数,并使用另一个子查询来查找最终分数最高的学生

WITH cte AS (
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY ID, CONVERT(varchar(7), datetimes, 126)
            ORDER BY datetimes DESC) rn
    FROM StudentMark
)

SELECT ID, Mark AS HighestMark
FROM
(
    SELECT *,
        RANK() OVER (PARTITION BY CONVERT(varchar(7), datetimes, 126)
            ORDER BY Mark DESC) rk
    FROM cte
    WHERE rn = 1
) t
WHERE rk = 1
ORDER BY ID;

您可以尝试以下方法

使用
行号()

SELECT * FROM
(
  SELECT *, 
   ROW_NUMBER() OVER(PARTITION BY YEAR(DATETIMES)
               ,MONTH(DATETIMES) ORDER BY MARK DESC) AS RN    
 FROM [MY_TABLE]
 )T WHERE RN=1
SELECT TOP 1 WITH TIES ID, mark AS HighestMarks
FROM [MY_TABLE]
ORDER BY ROW_NUMBER() OVER (PARTITION BY YEAR(datetimes)
                     ,MONTH(datetimes) ORDER BY mark DESC)
使用带领带的

SELECT * FROM
(
  SELECT *, 
   ROW_NUMBER() OVER(PARTITION BY YEAR(DATETIMES)
               ,MONTH(DATETIMES) ORDER BY MARK DESC) AS RN    
 FROM [MY_TABLE]
 )T WHERE RN=1
SELECT TOP 1 WITH TIES ID, mark AS HighestMarks
FROM [MY_TABLE]
ORDER BY ROW_NUMBER() OVER (PARTITION BY YEAR(datetimes)
                     ,MONTH(datetimes) ORDER BY mark DESC)
示例

WITH MY AS
(

SELECT
* FROM (VALUES
    (1001  , 10  , '2011-12-20'),
    (1002  , 11  , '2012-01-10'),
    (1005  , 12  , '2012-01-10'),
    (1003  , 10  , '2012-01-10'),
    (1004  , 11  , '2018-10-10'),
    (1006  , 12  , '2018-10-19'),
    (1007  , 13  , '2018-03-12'),
    (1008  , 15  , '2018-03-13')
    ) T( id , mark , datetimes)     
)

SELECT ID,Mark as HighestMark FROM
(
  SELECT *, 
  ROW_NUMBER() OVER(PARTITION BY YEAR(DATETIMES),MONTH(DATETIMES) ORDER BY MARK DESC) AS RN    
 FROM MY
 )T WHERE RN=1
输出:

ID    HighestMark
1001    10
1005    12
1008    15
1006    12

如果有超过1名学生获得相同的最高分数,则使用
RANK

select id, mark
from
(select *,  
 rank() over( partition by convert(char(7), datetimes, 111) order by mark desc) seqnum
from studentMark ) t
where seqnum = 1

在下面的查询中,您为Group By包含了ID列,因此,它将考虑所有ID的所有数据

Select Max(Mark)'HighestMark', ID From StudentMark Group BY Year(datetimes), Month(datetimes), ID
请从此脚本中删除ID列,然后重试。

这应该可以:

    select s.ID, t.Mark, t.[Month year] from Studentmark s
    inner join (
    Select 
Max(Mark)'HighestMark'
,cast(Year(datetimes) as varchar(10)) +  
 cast(Month(datetimes) as varchar(10)) [month year]
     From StudentMark
     Group BY cast(Year(datetimes) as varchar(10)) 
           +  cast(Month(datetimes) as varchar(10))) t on t.HighestMark = s.mark and  
t.[month year] = cast(Year(s.datetimes) as varchar(10)) +  cast(Month(s.datetimes) as varchar(10))

如果出于某种原因您厌恶子查询,您实际上可以这样做:

select distinct
      first_value(id) over (partition by year(datetimes), month(datetime) order by mark desc) as id
      max(mark) over (partition by year(datetimes), month(datetime))
from StudentMark;
或:


在这种情况下,您可以通过使用
rank()
densite\u rank()
而不是
row\u number()
问题来获取所有学生的情况。然而,请注意,从最终结果中去掉分区(年/月组合)会使它们变得神秘。@Clockwork Muse不,如果我读对了,这不是这个问题的重复。否则,OP的
GROUP BY
查询应该已经足够了,但显然不够。@TimBiegeleisen-那么为什么答案在功能上是相同的呢?这是最好的解决方案。我不明白为什么人们希望在日期上使用字符串函数,而内置的日期函数却做同样的事情。虽然Row_Number()超出了我所了解的范围,我花了很快的时间在谷歌上才弄清楚到底发生了什么。总而言之,这非常优雅,谢谢