这是我要查询的表格:
EmployeeId, Salary, Date
8, 500, 2016-11-02
8, 500, 2016-09-21
8, 500, 2016-10-18
9, 500, 2016-10-18
9, 500, 2016-09-21
9, 500, 2016-11-02
10, 1000, 2016-11-02
10, 700, 2016-09-21
我想选择一份员工名单,以及他们在该特定员工的最新日期工资。在样本数据的情况下,这是相同的日期(11-02),但不一定是这种情况。我的问题:
SELECT EmployeeId, Salary, MAX(Date)
FROM table
GROUP BY EmployeeId. Salary
ORDER BY EmployeeId
返回:
8, 500, 2016-11-02
9, 500, 2016-11-02
10, 700, 2016-09-21
10, 1000, 2016-11-02
我的预期输出是:
8, 500, 2016-11-02
9, 500, 2016-11-02
10, 1000, 2016-11-02
如果我在没有工资的情况下聚合,那么我会得到预期的结果,但我需要工资可见。有没有办法在聚合后包含它?
答案 0 :(得分:3)
在窗口函数之前(因为并非所有RDBMS版本都支持它们),您可以使用内联视图执行此操作。
首先考虑您的需求:
要实现第一个,我们会生成内联视图(别名" B"下面)。 然后我们加入到基集以检索其他所需信息;允许内连接消除不需要的记录;并完全否定对外部查询的需要。
SELECT A.EmployeeId, A.Salary, A.Date
FROM table A
INNER JOIN (SELECT max(date) mDate, EmployeeID
FROM table
GROUP BY EmployeeID) B
on A.EmployeeID = B.EmployeeID
and A.Date = B.MDate
ORDER BY EmployeeId
使用RDBMS时,可以根据集合来考虑数据,以及如何过滤这些集合并将它们连接在一起以实现所需的结果。对大多数(并非所有)RDBMS活动进行基于集合的处理将是最有效的。随着窗函数(Aka Analytical Functions)的引入,几代集可以在没有子查询的情况下完成;使它们成为数据分析的强大功能;虽然最初很难理解你的想法。
那么:ROW_NUMBER() OVER (PARTITION BY EmployeeId ORDER BY Date DESC) RN
究竟做了什么?
它按照日期降序的顺序为每个新员工遇到(分区)分配一个从1开始的行号(因此每个员工的最新日期将始终具有1的RN!)但是,1 isn'由于SQL操作顺序生成选择值LAST(因此where子句已经执行),因此可以在where子句中查询。这意味着要使窗口函数达到所需的结果并通过RN = 1限制,您必须将其包装在子查询中,然后您可以访问RN = 1,从而仅返回具有最新日期的员工的记录。由于RDBMS能够独立于分析函数执行表的生成,因此它可以同时处理它们并且非常快速地提供响应。
答案 1 :(得分:2)
您可以使用窗口功能选择最新的:
with cte as (
select EmployeeId,
Salary,
Date
ROW_NUMBER() OVER (PARTITION BY EmployeeId ORDER BY Date DESC) RN
from [table]
)
select EmployeeId,
Salary,
Date
from cte
where RN = 1
如果不清楚,您基本上是通过EmployeeId“分区”,按日期降序对每个分区内的行进行编号,然后选择此数字为1的行(即每个员工的最新行)。
答案 2 :(得分:1)
您可以使用窗口函数Row_Number()来查看最后一个值
Select *
From (
Select *,RN = Row_Number() over (Partition By EmployeeId Order by Date Desc)
From YourTable
) A
Where RN=1
答案 3 :(得分:1)
我倾向于使用APPLY执行这些操作。
SELECT t1.EmployeeId, t2.Salary, t2.Date
FROM table t1
CROSS APPLY (SELECT TOP 1 Salary, Date
FROM table
WHERE EmployeeId = t1.EmployeeId
ORDER BY Date DESC) t2
ORDER BY t1.EmployeeId