【问题标题】:CTE Row Number PartitioningCTE 行号分区
【发布时间】:2017-08-11 15:09:04
【问题描述】:

我很难找到关于我的 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

现在已经为每个销售人员生成了一个任务,其中一个,无论谁,都可以对任务做出反应,这将改变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

从上表可以看出,用户 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

所以这段 SQL 的问题之一是AND rn = 1,因为这是导致第 1 点中提出的问题的原因,但是如果我删除它并且状态发生变化,它将不会获得最新的任务项。另一方面,它也导致了这个问题。

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

[更新]:

任务表定义:

样本数据:

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

期望的输出:

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

17               | FooBar       | 281       | 26        | 6

【问题讨论】:

  • 您能否在此处添加您正在使用的完整架构和一些测试数据?例如,您的问题在示例数据中的任何位置都没有 ModifiedData 列。您能否还根据示例数据添加所需的输出,而不是试图解释它。
  • 嘿@iamdave,感谢您的回复。老实说,它涉及到很多,所以我会尽力分解它。
  • 您如何订购这些数据,因为这里的每个日期值都是相同的?这只是您的错字吗?
  • 不,这不是错字。我有一个存储过程,可以在某个系统事件上为所有销售资源插入任务。因此,它将为所有这些都插入相同的系统事件 - 状态 18 将表示等待预批准
  • @iamdave 非常感谢 - SqlZim 发布的答案似乎成功了:dense_rank()

标签: sql-server common-table-expression


【解决方案1】:

如果您显示您想要的结果,您的问题会更好,但我认为您可能想要做的是考虑使用除row_number() 之外的其他ranking 窗口函数,例如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

当最初将多条记录插入到您的 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 |
+------------------+------------+----------+------------+-------------+----+

它会返回:

+------------------+------------+----------+------------+-------------+----+
| 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 |
+------------------+------------+----------+------------+-------------+----+

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

【讨论】:

  • Holy smokes ... 甚至都不知道dense_rank() - 忙于实施以检查它是否可以说话 - 谢谢
  • @RichardBailey 乐于助人!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-19
  • 2021-08-07
  • 1970-01-01
  • 2012-06-15
相关资源
最近更新 更多