[英]SQL use of OVER and PARTITION BY
我有下表。
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
是必經之路的原因。
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
在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;
盡管可以使用窗口函數來表達此邏輯,但是橫向聯接(在SQL Server中使用apply
關鍵字實現)是表達邏輯的更自然的方式。
如果您不熟悉橫向聯接,則可以在from
子句中將它們視為相關的子查詢。 。 。 但是查詢允許您返回多個列。 不過,我應該補充一點,主要用例之一是表值函數,因此它是一個非常強大的構造。
首先,您需要為每個客戶端選擇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
我已經對其進行了處理,並且能夠產生所需的結果,請嘗試以下操作
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.