我很难找到关于我的CTE的正确逻辑。
一些背景信息:
系统中为具有销售角色的所有成员生成任务。这基本上将多个记录插入到我的Task
表中。 “任务”表格包含以下列:AssignedTo
和RequestedBy
- 其中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:
;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
答案 0 :(得分:2)
如果您展示了所需的结果,那么您的问题会更好,但我认为您可能想要考虑使用row_number()
以外的其他ranking
窗口函数,例如{{3} }
;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,其中只有一个用户正在看待挂起的任务。