Mic*_*man 3 sql select sql-server-2008-r2 greatest-n-per-group
我正在尝试从 SQL 中的数据集中选择最新的非零条目。大多数示例都满足于仅返回日期和分组变量,但我也想返回相关的值。例如:
ID Date Value
----------------------------
001 2014-10-01 32
001 2014-10-05 10
001 2014-10-17 0
002 2014-10-03 17
002 2014-10-20 60
003 2014-09-30 90
003 2014-10-10 7
004 2014-10-06 150
005 2014-10-17 0
005 2014-10-18 9
Run Code Online (Sandbox Code Playgroud)
使用
SELECT ID, MAX(Date) AS MDate FROM Table WHERE Value > 0 GROUP BY ID
Run Code Online (Sandbox Code Playgroud)
返回:
ID Date
-------------------
001 2014-10-05
002 2014-10-20
003 2014-10-10
004 2014-10-06
005 2014-10-18
Run Code Online (Sandbox Code Playgroud)
但是每当我尝试将 Value 作为选定变量之一包含在内时,SQLServer 都会导致错误:
“选择列表中的列 'Value' 无效,因为它不包含在聚合函数或 GROUP BY 子句中。”
我想要的结果是:
ID Date Value
----------------------------
001 2014-10-05 10
002 2014-10-20 60
003 2014-10-10 7
004 2014-10-06 150
005 2014-10-18 9
Run Code Online (Sandbox Code Playgroud)
我想到的一种解决方案是在原始表中查找结果并返回与相关 ID 和日期相对应的值(我已经修剪过,所以我知道这些是唯一的),但这在我看来就像一个凌乱的解决方案。对此的任何帮助将不胜感激。
注意:我不想按值分组,因为这是我最终试图提取的结果(即对于每个 ID,我想要最新的值)。进一步的例子:
ID Date Value
----------------------------
001 2014-10-05 10
001 2014-10-06 10
001 2014-10-10 10
001 2014-10-12 8
001 2014-10-18 0
Run Code Online (Sandbox Code Playgroud)
在这里,我只想要最后一个非零条目。(001, 2014-10-12, 8)
SELECT ID, MAX(Date) AS MDate, Value FROM Table WHERE Value > 0 GROUP BY ID, Value
Run Code Online (Sandbox Code Playgroud)
会返回:
ID Date Value
----------------------------
001 2014-10-10 10
001 2014-10-12 8
Run Code Online (Sandbox Code Playgroud)
这也可以使用窗口函数来完成,该函数比分组查询上的连接快得多:
select id, date, value
from (
select id,
date,
value,
row_number() over (partition by id order by date desc) as rn
from the_table
) t
where rn = 1
order by id;
Run Code Online (Sandbox Code Playgroud)
ID假设表中没有相同的重复日期,这应该有效:
SELECT A.ID, A.Date, A.Value
FROM
T1 AS A
INNER JOIN (SELECT ID,MAX(Date) AS Date FROM T1 WHERE Value > 0 GROUP BY ID) AS B
ON A.ID = B.ID AND A.Date = B.Date
Run Code Online (Sandbox Code Playgroud)