我正在开发一个 SQL Server 数据库,需要跟踪生产操作结果的进展情况。尝试每个操作 (OP),直到成功(结果 = 1)。如果操作失败(结果 = 0),则会重试给定的次数,如果通过,则继续执行下一个操作。
操作存储在名为 Operations 的表中,如下所示:
id | OP | 结果 |
---|---|---|
1 | 1 | 0 |
2 | 1 | 0 |
3 | 1 | 1 |
4 | 2 | 1 |
5 | 3 | 1 |
6 | 4 | 0 |
7 | 4 | 0 |
8 | 4 | 1 |
9 | 5 | 0 |
10 | 5 | 1 |
我想创建一个视图,以特定格式跨行显示每个操作的结果。如果操作失败,该行中的后续操作应显示为 NULL,直到操作成功。以下是 5 个操作所需的输出格式的示例:
OP 1 结果 | OP 2 结果 | OP 3 结果 | OP 4 结果 | OP 5 结果 |
---|---|---|---|---|
0 | 空 | 空 | 空 | 空 |
0 | 空 | 空 | 空 | 空 |
1 | 1 | 1 | 0 | 空 |
1 | 1 | 1 | 0 | 空 |
1 | 1 | 1 | 1 | 0 |
1 | 1 | 1 | 1 | 1 |
我尝试使用窗口函数和条件聚合来构建查询来旋转数据,但我正在努力正确传播结果并在失败后处理后续操作的 NULL。
到目前为止我得到的最好结果显示在this fiddle中,但我无法弄清楚如何合并已经成功的操作的NULL值。
这样的事情怎么样:
SELECT CASE WHEN max(OP) > 1 THEN 1 ELSE MAX(CASE WHEN OP = 1 THEN Outcome END) END AS OP1
, CASE WHEN max(OP) > 2 THEN 1 ELSE MAX(CASE WHEN OP = 2 THEN Outcome END) END AS OP2
, CASE WHEN max(OP) > 3 THEN 1 ELSE MAX(CASE WHEN OP = 3 THEN Outcome END) END AS OP3
, CASE WHEN max(OP) > 4 THEN 1 ELSE MAX(CASE WHEN OP = 4 THEN Outcome END) END AS OP4
, CASE WHEN max(OP) > 5 THEN 1 ELSE MAX(CASE WHEN OP = 5 THEN Outcome END) END AS OP5
FROM (
SELECT *
, sum(flag) OVER(ORDER BY OP, Outcome rows BETWEEN unbounded preceding AND CURRENT row) AS counter
FROM (
SELECT *
, CASE WHEN (lag(outcome) OVER(ORDER BY op,outcome) = outcome AND outcome = 1) OR (lag(outcome) OVER(ORDER BY op,outcome) <> outcome AND outcome = 0)
THEN 0
ELSE 1
END AS flag
FROM (
VALUES (1, 0)
, (1, 0)
, (1, 1)
, (2, 1)
, (3, 1)
, (4, 0)
, (4, 0)
, (4, 1)
, (5, 0)
, (5, 1)
) t (OP,Outcome)
) x
) x
GROUP BY x.counter
你需要的是创建“水平”,每当新的失败到来或新的成功时,它似乎都会增加,我称这个领域为
flag
。
然后创建一个计数器来计算该标志的总和,这将创建实际级别。
最后,进行生成列的条件聚合。为了在操作完成后处理 1,我使用
CASE WHEN max(OP) > 1 THEN 1
构造。
输出:
OP1 | OP2 | OP3 | OP4 | OP5 |
---|---|---|---|---|
0 | 空 | 空 | 空 | 空 |
0 | 空 | 空 | 空 | 空 |
1 | 1 | 1 | 0 | 空 |
1 | 1 | 1 | 0 | 空 |
1 | 1 | 1 | 1 | 0 |
1 | 1 | 1 | 1 | 1 |