如何使用单个SQL查询获取一个月内每个项目的最新条目

时间:2016-06-28 15:18:10

标签: sql-server

我正在尝试编写一个查询,为每个月的每个项目选择一个条目,但是从下表中选择本月的最新条目:

Name  | Date      | Value
a     |2015-01-01 |   1
a     |2015-01-02 |   2
b     |2015-01-03 |   1
b     |2015-01-04 |   1
b     |2015-01-03 |   3
c     |2015-01-02 |   2
c     |2015-01-29 |   10
a     |2015-02-10 |   2
a     |2015-02-20 |   1
c     |2015-02-10 |   2
c     |2015-02-22 |   23
b     |2015-02-25 |   1
b     |2015-02-19 |   2

返回应该是:

 a     |2015-01-02 |   2
 b     |2015-01-04 |   1
 c     |2015-01-29 |   10
 a     |2015-02-20 |   1
 b     |2015-02-25 |   1
 c     |2015-02-22 |   23

我想知道如何实现这一目标而不是每个月向SQL服务器发送多个查询我想用一个查询加载所有值然后过滤内存上的集合。否则我最终会写一个查询如下:

SELECT Name,Date, Value FROM MyTable mt
INNER JOIN (
select max(Date) as MaxDate
    FROM [MyTable] m WHERE YEAR(Date) =YEAR(@date) 
     AND MONTH(Date)=MONTH(@date)) mx ON t.Date = mx.MaxDate)

此查询需要每个月运行一次。

使用单个查询返回所有条目更好吗?

谢谢,

6 个答案:

答案 0 :(得分:1)

尝试在派生表中按年和月分组:

SELECT t1.Name, t1.[Date], t1.Value 
FROM MyTable t1
INNER JOIN (
   SELECT Name, YEAR(Date) AS y, MONTH([Date]) AS m, MAX([Date]) as MaxDate
   FROM MyTable  
   GROUP BY Name, YEAR(Date), MONTH([Date])
) t2 ON t1.Name = t2.Name AND
        YEAR(t1.[Date]) = t2.y AND MONTH(t1.[Date]) = t2.m AND 
        t1.[Date] = t2.MaxDate

答案 1 :(得分:0)

 SELECT *
 FROM (
      SELECT NAME, DATE, VALUE,
             ROW_NUMBER() OVER (PARTITION BY NAME, YEAR(Date), MONTH(Date) 
                                ORDER BY Date DESC) rn
      FROM MyTable) AS t
 WHERE t.rn = 1

答案 2 :(得分:0)

假设您使用的是支持它的SQL Server版本,您可以使用ROW_NUMBER()窗口函数返回每行的序列号,然后您可以使用它来限制只需要的行。

SELECT [Name],[Date],[Value]
  ,ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY [Date] DESC) AS [Seq]
FROM myTable

需要考虑的事项:

  • 领带时会发生什么? ROW_NUMBER将始终返回序列号,但如果您的数据有>在同一个Date值的1行,顺序将是arbritrary。要解决这个问题,请添加额外的抢占式ORDER BY条目
    • 如何过滤此内容?将其放入公用表表达式,内联视图或真实视图

答案 3 :(得分:0)

使用交叉申请

SELECT b.* 
FROM   mytable mt 
CROSS apply (SELECT TOP 1 NAME, date, value 
             FROM   [mytable] m 
             WHERE  m.NAME = mt.NAME 
               AND  Month(m.date) = Month(mt.date) 
               AND  Year(m.date) = Year(mt.date) 
             ORDER  BY m.date DESC) b 

答案 4 :(得分:0)

一旦你有一组不同的(Name,Month),我认为你需要一个相关的查询。有多种方法可以做到这一点,一种是使用cross apply

 select *
 from (select distinct Name, Month(Date) as Month
       from theTable) itemMonths
   cross apply (select Max(value)
                from theTable t
                where Month(t.Date) = itemMonths.Month
                     and t.Name = itemMonths.Name)

答案 5 :(得分:0)

您可以尝试以下方法:

WITH MyTable AS  (选择'a'AS名称,GETDATE()AS日期,1 AS值  UNION ALL  选择'a',GETDATE()+ 1,2  )  ,res AS(  SELECT Name,date,MAX(Date)OVER(PARTITION BY Name,DATEPART(yyyy,date),DATEPART(mm,date))AS max_date,Value FROM MyTable  )  SELECT name,date,res.value FROM res WHERE date = max_date

您仍需要过滤器,因为Max Over将返回所有行。

如果您使用的是Teradata,我建议使用Qualify Clause,但Itzik没有任何运气将这个移植到SQL服务器上! https://connect.microsoft.com/SQLServer/feedback/details/532474