2017-01-31 81 views
0

我有下表;SQL使用OVER和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天,發現使用OVERROW NUMBER()不同的方式,但我沒有很多的經驗其中。我之前發現的很多例子對於生成一個聚合表格都很好,但是我想保留整個表格,這就是爲什麼我認爲使用OVER是要走的路。

+1

添加你已經嘗試過的,你已經嘗試過什麼是您使用RDBMS東西 – davejal

+1

證明嗎?請同時使用產品和版本標籤。 –

+0

仍然錯過了你試過的完整查詢,請仔細閱讀爲什麼這很重要[mcve] – davejal

回答

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 
+0

天才就是這樣。非常感謝Zohar。這是一個簡單的解決方案。對不起,如果我已經搞砸了發佈的要求,所有人都對不起。我一直在使用網站學習如何編寫代碼,但這是我的第一篇文章,我花了大約一個小時試圖解決如何將實際文章放在一起。感謝所有的答案和輸入 –

0

首先,您需要選擇LatestEpisode每每一個客戶,然後你可以使用這個值來標識行,在那裏你可以從

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 

得到LatestLocation您還可以使用公用表表達式(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 
+0

請閱讀【答案】寫出更好的答案,代碼只是答案,不幫助OP理解爲什麼這個答案有幫助 – davejal

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子句中相關子查詢。 。 。但允許您返回多個列的查詢。不過,我應該補充一點,主要用例之一是表值函數,所以它是一個非常強大的構造。

+0

不應該在'e2。[Date]'desc?以及爲什麼當你只需要'episode'和'location'時選擇*'? –

+0

@ZoharPeled。 。 。 「日期」似乎是三個字符的字符串,沒有自然順序。而且,'select *'很好。優化器選擇所需的列。 –

+0

不知道在交叉申請中的select *,謝謝。我猜測日期是適當的數據類型,只需在這種格式的問題中輸入 –

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 
相關問題