CTE行号分区

Ric*_*ley 7 sql-server common-table-expression

我正在努力找到关于我的CTE的正确逻辑.

一些背景资料:

系统中为具有销售角色的所有成员生成任务.这基本上会在我的Task表中插入多条记录.任务表包括以下列:AssignedToRequestedBy- 其中AssignedTo将有每个销售成员Id.目前所有销售人员都可以看到该任务,因为没有人声称它:

ApprovalStatusId EntityType     EntityId    AssignedTo      RequestedBy
18               | FooBar       | 281       | 4             | 6
18               | FooBar       | 281       | 9             | 6
18               | FooBar       | 281       | 17            | 6
18               | FooBar       | 281       | 26            | 6
18               | FooBar       | 281       | 39            | 6
Run Code Online (Sandbox Code Playgroud)

现在已经为每个销售人员生成了一个任务,其中一个任务无关紧要,谁可以对任务做出反应,这将改变AssignedTo任务状态和任务状态:

ApprovalStatusId  EntityType    EntityId    AssignedTo    RequestedBy
18               | FooBar       | 281       | 4         | 6
18               | FooBar       | 281       | 9         | 6
18               | FooBar       | 281       | 17        | 6
18               | FooBar       | 281       | 26        | 6
18               | FooBar       | 281       | 39        | 6
17               | FooBar       | 281       | 26        | 6
1                | FooBar       | 281       | 6         | 6
Run Code Online (Sandbox Code Playgroud)

从上表中可以看出,用户26对任务做出了反应并更改了状态.完成后,系统将任务重定向回原始请求,即用户6 - 状态也已更改以指示此操作.

问题:

  1. 目前,只有一个用户(Id 4)看到分配给所有销售用户的任务

我尝试过的:

解决#1:

;WITH cte AS
(
   SELECT task.*, stat.Name AS StatusName,
         ROW_NUMBER() OVER (PARTITION BY EntityId, EntityType ORDER BY ModifiedData DESC) AS rn
   FROM dbo.Task task
   INNER JOIN dbo.ApprovalStatus stat on task.ApprovalStatusId = stat.ApprovalStatusId
)

SELECT *
FROM cte    
WHERE AssignedTo = @resourceId 
AND StatusName like 'Pending%'
AND rn = 1
Run Code Online (Sandbox Code Playgroud)

因此,这段SQL的一个问题是AND rn = 1,因为这是导致第1点引发问题的原因,但如果我删除它并且状态发生变化,它将无法获得最新的任务项.另一方面,它也导致了这个问题.

我也尝试将分区更改为:PARTITION BY EntityId, EntityType, AssignedTo ORDER BY ModifiedData DESC,但问题是,rn在大多数情况下,它会产生等于1的值,这将不会产生基于销售组的正确结果.

[更新]:

任务表定义: 在此输入图像描述

样本数据:

Comments     InsertDate                     ModifiedData                CommentUserId   ApprovalStatusId    EntityType      EntityId     TenantId    AssignedTo  RequestedBy
...         |   2017-03-20 11:18:06.343|    2017-03-20 11:18:06.343|    NULL            |   18              |   FooBar     |    75      |7              |4              |42
...         |   2017-03-20 11:18:06.343|    2017-03-20 11:18:06.343|    NULL            |   18              |   FooBar     |    75      |7              |6              |42
...         |   2017-03-20 11:18:06.343|    2017-03-20 11:18:06.343|    NULL            |   18              |   FooBar     |    75      |7              |9              |42
...         |   2017-03-20 11:18:06.343|    2017-03-20 11:18:06.343|    NULL            |   18              |   FooBar     |    75      |7              |17             |42
...         |   2017-03-20 11:18:06.343|    2017-03-20 11:18:06.343|    NULL            |   18              |   FooBar     |    75      |7              |26             |42
...         |   2017-03-20 11:18:06.343|    2017-03-20 11:18:06.343|    NULL            |   18              |   FooBar     |    75      |7              |39             |42
...         |   2017-03-20 11:18:06.343|    2017-03-20 11:18:06.343|    NULL            |   18              |   FooBar     |    75      |7              |67             |42
...         |   2017-03-20 11:18:06.343|    2017-03-20 11:18:06.343|    NULL            |   18              |   FooBar     |    75      |7              |10073          |42
...         |   2017-03-20 11:18:06.343|    2017-03-20 11:18:06.343|    NULL            |   18              |   FooBar     |    75      |7              |10164          |42
Run Code Online (Sandbox Code Playgroud)

期望的输出:

声明该任务的销售用户应该是唯一可以看到它的人.换句话说,销售用户应该能够看到此记录(在第二个表示例中可见) - 所有其他销售用户应该看不到任何内容

17               | FooBar       | 281       | 26        | 6
Run Code Online (Sandbox Code Playgroud)

Sql*_*Zim 2

如果你展示了你想要的结果,你的问题会更好,但我认为你可能想要做的是考虑使用ranking除 之外的不同窗口函数row_number(),例如dense_rank()

;WITH cte AS
(
   SELECT task.*, stat.Name AS StatusName,
         dense_rank() OVER (PARTITION BY EntityId, EntityType ORDER BY ModifiedData DESC) AS dr
   FROM dbo.Task task
   INNER JOIN dbo.ApprovalStatus stat on task.ApprovalStatusId = stat.ApprovalStatusId
)

SELECT *
FROM cte    
WHERE AssignedTo = @resourceId 
AND StatusName like 'Pending%'
AND dr = 1
Run Code Online (Sandbox Code Playgroud)

当多条记录最初插入到task表中时,cte 返回的不是:

+------------------+------------+----------+------------+-------------+----+
| ApprovalStatusId | EntityType | EntityId | AssignedTo | RequestedBy | rn |
+------------------+------------+----------+------------+-------------+----+
|               18 | FooBar     |     281  |          4 |           6 |  1 |
|               18 | FooBar     |     281  |          9 |           6 |  2 |
|               18 | FooBar     |     281  |         17 |           6 |  3 |
|               18 | FooBar     |     281  |         26 |           6 |  4 |
|               18 | FooBar     |     281  |         39 |           6 |  5 |
+------------------+------------+----------+------------+-------------+----+
Run Code Online (Sandbox Code Playgroud)

它将返回:

+------------------+------------+----------+------------+-------------+----+
| ApprovalStatusId | EntityType | EntityId | AssignedTo | RequestedBy | dr |
+------------------+------------+----------+------------+-------------+----+
|               18 | FooBar     |     281  |          4 |           6 |  1 |
|               18 | FooBar     |     281  |          9 |           6 |  1 |
|               18 | FooBar     |     281  |         17 |           6 |  1 |
|               18 | FooBar     |     281  |         26 |           6 |  1 |
|               18 | FooBar     |     281  |         39 |           6 |  1 |
+------------------+------------+----------+------------+-------------+----+
Run Code Online (Sandbox Code Playgroud)

这样就可以解决问题#1,即只有一个用户看到待处理的任务。