Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在带有Rownumber的CTE中,使用Where子句设置条件的位置_Sql Server_Tsql - Fatal编程技术网

Sql server 在带有Rownumber的CTE中,使用Where子句设置条件的位置

Sql server 在带有Rownumber的CTE中,使用Where子句设置条件的位置,sql-server,tsql,Sql Server,Tsql,当使用CTE和ROW\u NUMBER OVER PARTITION时,我有点困惑,在哪里可以添加条件 我有一个包含以下列的表: UserID、BranchNumber、MemberDate和MemberStatus 注意:一个成员可以在不同的位置拥有多个成员身份: 下面的代码让我少了一条记录:17069 以下代码提供了一条附加记录:17070 我只是不明白为什么会有这样的区别,哪种方式才是正确的 正确的记录数量是19000条。从某种意义上说,这两条记录都是“正确的”,它们都返回了所请求的内容。

当使用
CTE
ROW\u NUMBER OVER PARTITION
时,我有点困惑,在哪里可以添加条件

我有一个包含以下列的表:

UserID、BranchNumber、MemberDate
MemberStatus

注意:一个成员可以在不同的位置拥有多个成员身份:

下面的代码让我少了一条记录:17069

以下代码提供了一条附加记录:17070

我只是不明白为什么会有这样的区别,哪种方式才是正确的


正确的记录数量是19000条。

从某种意义上说,这两条记录都是“正确的”,它们都返回了所请求的内容。(2) 提供更多记录,因为您在子查询(cte)中应用了额外条件(
MemberStatus='Active'
)。因此,MemberStatus不等于“Active”的记录不能有“RowNumber=1”。(1) 不过滤CTE中的此类行,因此它可能返回
RowNumber=1和MemberStatus“Active”
的记录,这些记录通过在外部查询中应用条件从最终结果集中删除。

查询是不同的,因此我希望记录是不同的

第一个问题是:

  • 获取
    BranchNumber=1
    的所有记录,按
    MemberDate
    userId上的分区排序
  • 然后,从该结果集中,仅当
    MemberStatus处于活动状态时,为每个用户获取1st记录
第二个问题是:

  • BranchNumber=1
    获取所有
    activemember
    记录,按用户ID上的
    MemberDate
    分区排序
  • 然后,根据上面的结果,给我第一个实例

因此,第一个结果集可能是从用户处获取最新的记录,不管是非活动记录还是非活动记录,然后过滤掉非活动记录。第二个将只返回活动记录,因此我希望得到更多。

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视为虚拟表。您可以通过从CTE1将最终选择更改为
select*来调试此功能。只需查看返回的内容。

因为您提到了“一个成员可以在不同的位置拥有多个成员身份”,请尝试将其按
“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'

没有更好的地方可以添加条件。只有一个正确的地方。这取决于你需要什么。我不清楚你需要什么。您想要第一个活动的项目,还是想要第一个活动的项目?我想要所有最新的
活动的
记录和
分支01
。我想说,在CTE中使用
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
;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'