TL; DR:向下滾動到任務2LAG偏移
我處理以下數據集:
email,createdby,createdon
[email protected],jsmith,2016-10-10
[email protected],nsmythe,2016-09-09
[email protected],vstark,2016-11-11
[email protected],ajohnson,2015-02-03
[email protected],elear,2015-01-01
...
等。每封電子郵件都保證在數據集中至少有一個副本。
現在,有兩個任務需要解決;我解決了其中一個,但我正在與另一個掙扎。現在我將介紹這兩個任務的完整性。
TASK 1(解決): 對於每一行,每封電子郵件,與與此電子郵件創建的第一個記錄的用戶名返回的附加列。
對於上述試樣數據集合預期結果:
email,createdby,createdon,original_createdby
[email protected],jsmith,2016-10-10,nsmythe
[email protected],nsmythe,2016-09-09,nsmythe
[email protected],vstark,2016-11-11,nsmythe
[email protected],ajohnson,2015-02-03,elear
[email protected],elear,2015-01-01,elear
代碼以得到上面的:
;WITH q0 -- this is just a security measure in case there are unique emails in the data set
AS (SELECT t.email
FROM t
GROUP BY t.email
HAVING COUNT(*) > 1) ,
q1
AS (SELECT q0.email
, createdon
, createdby
, ROW_NUMBER() OVER (PARTITION BY q0.email ORDER BY createdon) rn
FROM t
JOIN q0
ON t.email = q0.email)
SELECT q1.email
, q1.createdon
, q1.createdby
, LAG(q1.createdby, q1.rn - 1) OVER (ORDER BY q1.email, q1.createdon) original_createdby
FROM q1
ORDER BY q1.email
, q1.rn
簡要說明:我分區數據通過電子郵件設置,那麼我在每個分區數目的行按創建日期排序,最後我從(rn-1)記錄返回[createdby]值。完全按照預期工作。
現在,類似上面有任務2:
任務2: 對於每一行,每封電子郵件,返回創建的第一個重複的用戶名。即其中rn = 2的用戶名稱。
預期結果:
email,createdby,createdon,first_dupl_createdby
[email protected],jsmith,2016-10-10,jsmith
[email protected],nsmythe,2016-09-09,jsmith
[email protected],vstark,2016-11-11,jsmith
[email protected],ajohnson,2015-02-03,ajohnson
[email protected],elear,2015-01-01,ajohnson
我希望保持高性能,從而試圖採用超前滯後功能:
WITH q0
AS (SELECT t.email
FROM t
GROUP BY t.email
HAVING COUNT(*) > 1) ,
q1
AS (SELECT q0.email
, createdon
, createdby
, ROW_NUMBER() OVER (PARTITION BY q0.email ORDER BY createdon) rn
FROM t
JOIN q0
ON t.email = q0.email)
SELECT q1.email
, q1.createdon
, q1.createdby
, q1.rn
, CASE q1.rn
WHEN 1 THEN LEAD(q1.createdby, 1) OVER (ORDER BY q1.email, q1.createdon)
ELSE LAG(q1.createdby, q1.rn - 2) OVER (ORDER BY q1.email, q1.createdon)
END AS first_dupl_createdby
FROM q1
ORDER BY q1.email
, q1.rn
說明:在每個分區的第一個記錄,返回[createdby]來自以下記錄(即來自包含第一個副本的記錄)。對於同一分區中的所有其他記錄,從[rn-2]記錄前返回[createdby](即對於rn = 2,我們保留在同一記錄上,對於rn = 3,我們將返回1記錄,對於rn = 4 - 2記錄等)。
一個問題出現在
ELSE LAG(q1.createdby, q1.rn - 2)
操作。顯然,對任何邏輯,儘管前面的行的存在(當1 THEN ...)時,ELSE塊也評價RN = 1,導致傳遞給LAG功能的負的偏移值:
消息8730,等級16,狀態2,行37 滯後和導聯函數的偏移參數不能爲負值。
當我註釋到ELSE行時,整個事情都很好,但顯然我沒有在first_dupl_createdby列中得到任何結果。
問題: 是否有任何方式重寫上述CASE語句(在任務#2中),以便它始終從每個分區中的rn = 2的記錄返回值,但這是重要的位 - 沒有進行自我JOIN操作(我知道我可以在單獨的子查詢中準備rn = 2的行,但是這意味着整個表上會有額外的掃描,並且還會運行不必要的自動JOIN)。
編輯你的問題,包括*結果*您希望得到您的樣本數據。 –
這可能聽起來很愚蠢,但是如果在'q1'中使用'ROW_NUMBER()... + 2'作爲'rn'呢?在你的'case'表達式中,你可以使用'CASE q1.rn當3 then ...... ELSE LAG(q1.createdby,q1.rn)' – Lamak