我有一个表vwuser。我想用表值函数fnuserrank(userID)连接这个表。所以我需要交叉应用表值函数:
SELECT *
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
对于每个userID,它会生成多个记录。我只希望每个empid的最后一条记录没有Term of Term(inated)。我怎么能这样做?
数据:
HistoryID empid Rank MonitorDate 1 A1 E1 2012-8-9 2 A1 E2 2012-9-12 3 A1 Term 2012-10-13 4 A2 E3 2011-10-09 5 A2 TERM 2012-11-9
必须从第2条记录和第4条记录中选择。
答案 0 :(得分:3)
在SQL Server 2005+中,您可以使用此公用表表达式(CTE)来确定MonitorDate的最新记录,该记录没有“Term”等级:
WITH EmployeeData AS
(
SELECT *
, ROW_NUMBER() OVER (PARTITION BY empId, ORDER BY MonitorDate DESC) AS RowNumber
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
WHERE Rank != 'Term'
)
SELECT *
FROM EmployeeData AS ed
WHERE ed.RowNumber = 1;
注意:此CTE之前的语句需要以分号结尾。因此,我看到很多人都像;WITH EmployeeData AS...
答案 1 :(得分:2)
你必须要玩这个。无法在sqlfiddle上模拟您的架构。
Select bar.*
from
(
SELECT *
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
where rank != 'TERM'
) foo
left join
(
SELECT *
FROM vwuser AS b
CROSS APPLY fnuserrank(b.userid)
where rank != 'TERM'
) bar
on foo.empId = bar.empId
and foo.MonitorDate > bar.MonitorDate
where bar.empid is null
我总是需要在更高的日期测试左外。。它的工作方式是你做左外。除每个用户一行外,每行都有一个具有更高监视日期的行。那一排是你想要的那一排。我通常使用我的代码中的一个例子,但我在错误的笔记本电脑上。为了使它工作,您可以选择foo。,bar。并查看结果并找到您想要的行并使条件正确。
您也可以这样做,这更容易记住
SELECT *
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
) foo
join
(
select empid, max(monitordate) maxdate
FROM vwuser AS b
CROSS APPLY fnuserrank(b.userid)
where rank != 'TERM'
) bar
on foo.empid = bar.empid
and foo.monitordate = bar.maxdate
我通常更喜欢使用基于集合的逻辑而不是聚合函数,但无论如何都可行。您也可以通过将TVF联接的结果缓存到表变量中来调整它。
编辑: http://www.sqlfiddle.com/#!3/613e4/17 - 我在这里嘲笑你的TVF。显然,sqlfiddle不喜欢“去”。
select foo.*, bar.*
from
(
SELECT f.*
FROM vwuser AS a
join fnuserrank f
on a.empid = f.empid
where rank != 'TERM'
) foo
left join
(
SELECT f1.empid [barempid], f1.monitordate [barmonitordate]
FROM vwuser AS b
join fnuserrank f1
on b.empid = f1.empid
where rank != 'TERM'
) bar
on foo.empId = bar.barempid
and foo.MonitorDate > bar.barmonitordate
where bar.barempid is null