提问人:Zenith 提问时间:3/8/2023 最后编辑:Zenith 更新时间:3/9/2023 访问量:131
如何从一组状态中计算总进度状态?
How to calculate total progress status from a group of statuses?
问:
我正在尝试检索存储在 sql server 数据库中的多步骤进程的状态。每个步骤都是表中的一条记录。
当客户端想知道该过程的状态时,我想检索所有步骤的状态,并让我的查询返回状态
- 当所有步骤的状态都为“已排队”时,为“已排队”,
- 当其中一个步骤的状态为“正在进行”时,为“正在进行”,
- 当所有步骤的状态都为“已完成”时,为“已完成”。
此查询会是什么样子?
我在 Sql 方面还没有那么有经验,所以我还没有尝试过任何东西,因为我不知道从哪里开始,也无法在 Google 上真正找到类似这个问题的东西。
根据评论进行编辑: 表格如下所示:
Process
- id uniqueidentifier not null pk
- other stuff
Step
- id uniqueidentifier not null pk
- processId uniqueidentifier not null fk with process.id
- status nvarchar(30) not null
因此,步骤的一些示例数据将是:
编号 | 进程 Id | 地位 |
---|---|---|
ED9D1F80-1941-495A-A282-833FDDF41174 | 6F940376-27B5-4899-8CF0-BEB89877DA46 | 进行中 |
2738A403-7AD4-4396-9B5C-C641BC01F96F | 6F940376-27B5-4899-8CF0-BEB89877DA46 | 排队 |
4e6a0c8e-49e9-4dc6-adbe-a74f27aff36f | 6F940376-27B5-4899-8CF0-BEB89877DA46 | 排队 |
这应该导致我的查询返回:
进程 Id | 地位 |
---|---|
6F940376-27B5-4899-8CF0-BEB89877DA46 | 进行中 |
答:
1赞
Ian Boyd
3/8/2023
#1
您可以使用以下查询进行检查:
DECLARE @pid int = 7; --whatever the ID of this process is.
SELECT
CASE
WHEN EXISTS (SELECT 1 FROM ProcessSteps WHERE ProcessID = @pid AND Status = 'in-progress') THEN 'in-progress'
WHEN NOT EXISTS (SELECT 1 FROM ProcessSteps WHERE ProcessID = @pid AND Status = 'finished') THEN 'queued'
ELSE 'finished'
END AS ProcessStatus
FROM ProcessSteps
WHERE ProcessID = @pid
查询首先检查是否有任何步骤是 。如果有,则返回 的状态。接下来是检查所有步骤是否都已完成,如果未返回,则返回 。in-progress
in-progress
queued
finished
评论
0赞
Zenith
3/8/2023
谢谢!这对我有用。我很确定将来会添加更多状态,但我了解语法,所以我可能会解决它。
0赞
Sean Lange
3/8/2023
这当然会起作用,但在较大的桌子上,性能可能会成为一个问题。子查询作为一列将显著影响性能。
2赞
Joel Coehoorn
3/8/2023
#2
这应该有效,并且可能表现得更好:
SELECT processId, status
FROM (
select processId, status
, row_number() over (partition by processid
order by case when status = 'in-progress' then 0
when status = 'queued' then 1
else 2 end) rn
from Step
) t
WHERE rn = 1
但是在原始帖子中有一个重要的未回答的问题,即如果只有 和 项目混合在一起,没有列出任何内容,该怎么办。在这个答案中,我偏向于较早的状态。queued
finished
in-progress
queued
如果将来可以有更多状态值,我可能会这样做:
SELECT processId, status
FROM (
select processId, Step.status
, row_number() over (partition by processid
order by coalesce(map.priority,100)) rn
from Step
left join ( values
('in-progress', 0),
('queued', 1),
('finished' 2)
) map(status, priority) ON map.status = Step.status
) t
WHERE rn = 1
这将以更简洁的方式列出映射,缩进更少,使其更易于阅读和维护。它还使您可以轻松地转换为状态表。and instead of 是,因此,如果在更新查询之前添加了状态以了解它,则查询不会完全跳过行。LEFT JOIN
coalesce()
INNER JOIN
上一个:如何序列化泛型对象
评论