簡體   English   中英

SQL使用OVER和PARTITION BY

[英]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,並發現了使用OVERROW 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM