我正在尝试编写一个查询,为每个月的每个项目选择一个条目,但是从下表中选择本月的最新条目:
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)
此查询需要每个月运行一次。
使用单个查询返回所有条目更好吗?
谢谢,
答案 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
需要考虑的事项:
答案 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