我有下表;
ClientID | Location | Episode | Date
001 | Area1 | 4 | 01Dec16
001 | Area2 | 3 | 01Nov16
001 | Area2 | 2 | 01Oct16
001 | Area1 | 1 | 01Sep16
002 | Area2 | 3 | 21Dec16
002 | Area1 | 2 | 21Nov16
002 | Area1 | 1 | 21Oct16
我希望根据客户端的最新一集创建2个新列
ClientID | Location | Episode | Date | LatestEpisode | LatestLocation
001 | Area1 | 4 | Dec | 4 | Area1
001 | Area2 | 3 | Nov | 4 | Area1
001 | Area2 | 2 | Oct | 4 | Area1
001 | Area1 | 1 | Sep | 4 | Area1
002 | Area2 | 3 | Dec | 3 | Area2
002 | Area1 | 2 | Nov | 3 | Area2
002 | Area1 | 1 | Oct | 3 | Area2
我已经解决了我可以使用OVER
来制作LatestEspisode:
LatestEpisode = MAX(Episode) OVER(PARTITION BY ClientID)
但是无法弄清楚如何获取LatestLocation?
编辑:对不起,如果我没有正确的格式,这是我的第一篇文章。我试图看看如何正确发布,但我发现它很混乱
我在过去3天内多次搜索stackoverflow,并使用OVER
和ROW NUMBER()
找到了各种方法,但我对它们没有太多经验。我之前发现的许多示例都适用于生成聚合表,但我想保留完整的表,这就是为什么我认为使用OVER
是可行的方法。
答案 0 :(得分:2)
Sql server 2012版本引入了FIRST_VALUE()
函数,
这使您可以像这样编写选择查询:
SELECT ClientID,
Location,
Episode,
[Date],
LatestEpisode = FIRST_VALUE(Episode) OVER(PARTITION BY ClientID ORDER BY [Date] DESC),
LatestLocation = FIRST_VALUE(Location) OVER(PARTITION BY ClientID ORDER BY [Date] DESC)
FROM tableName
答案 1 :(得分:1)
在SQL Server中,我会使用cross apply
执行此操作:
select e.*, e2.episode as LatestEpisode, e2.location as LatestLocation
from episodes e cross apply
(select top 1 e2.*
from episodes e2
where e2.clientId = e.clientId
order by e2.episode desc
) elast;
尽管您可以使用窗口函数表达此逻辑,但横向连接(使用apply
关键字在SQL Server中实现)是表达逻辑的更自然的方式。
如果您不熟悉横向连接,可以将它们视为from
子句中的相关子查询。 。 。但是允许您返回多个列的查询。不过,我应该补充说,其中一个主要用例是表值函数,因此它是一个非常强大的构造。
答案 2 :(得分:0)
首先,您需要为每个客户选择LatestEpisode
,然后您可以使用此值来标识行,您可以从中获取LatestLocation
SELECT *
,(
SELECT Location
FROM Episodes
WHERE ClientId = MyTable.ClientId
AND Episode = MyTable.LatestEpisode
) AS LatestLocation
FROM (
SELECT *
,MAX(Episode) OVER (PARTITION BY ClientId) AS LatestEpisode
FROM Episodes
) AS MyTable
您还可以使用公用表表达式(CTE):
WITH cte
AS (
SELECT *
,MAX(Episode) OVER (PARTITION BY ClientId) AS LatestEpisode
FROM Episodes
)
SELECT cte.*
,(
SELECT Location
FROM Episodes
WHERE ClientId = cte.ClientId
AND Episode = cte.LatestEpisode
) AS LatestLocation
FROM cte
答案 3 :(得分:0)
我已经研究过并且能够产生所需的结果 请尝试以下
Declare @Table table ( ClientID varchar(max), Location varchar(500), Episode int, Dated varchar(30))
Insert Into @Table
Values ('001', 'Area1', 4 ,'01Dec16' )
,('001', 'Area2', 3, '01Nov16')
, ('001', 'Area2', 2, '01Oct16')
,('001' ,'Area1' ,1, '01Sep16')
,('002' ,'Area2' ,3, '21Dec16')
,('002' ,'Area1' ,2, '21Nov16')
,('002' ,'Area1' ,1, '21Oct16')
; WITH LL AS
(
SELECT CLientID ,MAX(CAST (Dated as Date)) as maxdate
FROM @table
GROUP BY ClientID
)
, Area AS
(
SELECT Location, x.ClientID, x.Dated FROM @Table x INNER JOIN LL b ON x.ClientID = b.ClientID AND x.Dated = b.maxdate
)
SELECT a.*
, LatestEpisode = MAX(Episode) OVER(PARTITION BY a.ClientID)
, LatestLocation = b.Location
FROM @Table a
INNER JOIN Area b ON a.ClientID = b.ClientID