2013-12-21 57 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'