2013-12-21 59 views
2

我對使用CTEROW_NUMBER OVER PARTITION時在哪裏添加條件的首選位置有點困惑。哪裏可以設置條件與CTE中的哪裏條款使用Rownumber

我有含有下列的表:

UserID, BranchNumber, MemberDateMemberStatus

注意:一個構件可具有在不同位置的多個成員資格:

下面的代碼給我一個少記錄:17069

WITH CTE AS 
(
SELECT 
* 
,ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY [MemberDate] DESC) AS RowNumber 

FROM MemberTable 

WHERE BranchNumber = '01' 
) 
SELECT * FROM CTE WHERE RowNumber = 1 AND MemberStatus = 'Active' 

下面的代碼提供了一個額外的記錄:17070

WITH CTE AS 
(
SELECT 
* 
,ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY [MemberDate] DESC) AS RowNumber 

FROM MemberTable 

WHERE BranchNumber = '01' AND MemberStatus = 'Active' 
) 
SELECT * FROM CTE WHERE RowNumber = 1 

我只是困惑,爲什麼差異,這是正確的方式?

正確的記錄量爲19000

+0

有沒有首選的地方添加條件。只有一個*正確*的地方。這取決於你需要什麼。我不清楚你需要什麼。你想要第一個活動的項目,還是你想要第一個活動的項目? – usr

+0

我希望所有最近的記錄是'活躍'和'分支01'。 – Asynchronous

+0

我會說使用CTE內的'WHERE'過濾掉不需要的行,然後再過濾。 –

回答

1

兩者都是「正確的」,在某種意義上,他們回到什麼是問。 (2)提供更多的記錄,因爲您在子查詢(cte)中應用了額外的條件(MemberStatus = 'Active')。因此,記錄MemberStatus不等於「活動」的位置不能有「RowNumber = 1」。 (1)不會過濾CTE中的此類行,因此可能會返回記錄[s],其中RowNumber=1 and MemberStatus <> 'Active'通過應用外部查詢中的條件從最終結果集中移除。

0

查詢是不同的,所以我希望記錄是不同的。

第一個查詢說:

  • 獲取所有記錄,其中BranchNumber = 1,以便通過MemberDate和分區上userId
  • 然後,從該結果集,給我把記錄每一個用戶,只有當MemberStatus is Active

第二個查詢說:

  • 給我所有activemember記錄從BranchNumber = 1,以便通過MemberDatepartition on userId
  • 然後,從上述結果,讓我的第一實例。

因此,第一個結果集可能會從用戶獲取最新記錄,不活動或不活動,然後過濾出非活動記錄。第二個將只返回活動記錄,所以我期望更多。

0

ROW_NUMBER的評估是在WHERE之後。讓我們通過將兩者分開來讓它更直觀:

WITH CTE1 AS 
(
SELECT 
* 

FROM MemberTable 

WHERE BranchNumber = '01' AND MemberStatus = 'Active' 
) 
, CTE2 AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY [MemberDate] DESC) AS RowNumber 
    FROM CTE1 
) 
SELECT * FROM CTE2 WHERE RowNumber = 1 

我認爲現在需要首先應用過濾器纔是非常明顯的。將CTE視爲虛擬表。您可以通過將最終選擇更改爲SELECT * FROM CTE1進行調試。只要看看返回的是什麼。

0

既然你提到「成員可以在不同的位置有多個成員」,嘗試由"BranchNumber"以及對它進行分區,看看它給你你正在尋找的結果。

你這樣做的方式,它返回任何位置的最後一個成員開始日期,如果你用BranchNumber進行分區,它將返回每個分支號碼的最後一個成員開始日期,嘗試類似這

;WITH 
CTE 
AS 
    (
    SELECT * 
    ,ROW_NUMBER() OVER (PARTITION BY UserID, BranchNumber ORDER BY [MemberDate] DESC) 
                    AS RowNumber 
    FROM MemberTable 

) 
SELECT * FROM CTE 
WHERE RowNumber = 1 AND MemberStatus = 'Active'