SQL迭代没有游标的行
Posted
技术标签:
【中文标题】SQL迭代没有游标的行【英文标题】:SQL Iterate over row without a cursor 【发布时间】:2020-10-14 10:59:40 【问题描述】:我有一些读取传感器状态的数据。传感器每 15 分钟报告一次状态。这有点像......
Sensor ID, Status, TimeStamp, **WhatIWantSessionID**
1, Off, 0345, **0**
1, Charge, 0400, **1**
1, Charge, 0415, **1**
1, Off, 0430, **0**
1, Charge, 0445, **2**
1, Off, 0500, **0**
"WhatIWantSessionID" ...我想在每次 Charge 会话开始时设置一个递增的 sessionID。保持该 sessionID 直到状态切换状态。以下链接非常棒,“几乎”可以满足我的需要,但并不完全(因为我没有在会话中开始/停止的标志)。非常感谢帮助。 Iterate over rows using SQL
【问题讨论】:
感谢 a_horse ... Lag(),Lead() 看起来不错。 【参考方案1】:必须有更好的方法来做到这一点,但下面的例子有效(丑陋,我相信有人会发布一些聪明而聪明的东西,但我今天还没有足够的咖啡来做聪明,并且有效)。
create or replace temporary table stacko_64351844 (
id number,
status varchar(20),
ts varchar(20),
desired number);
INSERT INTO stacko_64351844
VALUES
(1, 'Off', '0345', 0),
(1, 'Charge', '0400', 1),
(1, 'Charge', '0415', 1),
(1, 'Off', '0430', 0),
(1, 'Charge', '0445', 2),
(1, 'Off', '0500', 0),
(1, 'Charge', '0515', 3),
(1, 'Charge', '0530', 3),
(1, 'Charge', '0545', 3),
(1, 'Charge', '0600', 3),
(1, 'Off', '0615', 0);
SELECT id,
status, ts,
desired,
NVL(calc_desired, max(calc_desired) over (partition by id order by id, ts rows between unbounded preceding and current row)) as calc_desired
FROM (
SELECT id,
status,
ts,
desired,
tmp_desired,
CASE
WHEN status = 'Off' THEN 0
WHEN (status != 'Charge' AND status = lag(status, 1, null)
over (partition by id order by id, ts, status DESC) )
THEN null
ELSE
sum(tmp_desired) over (partition by id, tmp_desired order by id, ts rows between unbounded preceding and current row)
end as calc_desired
FROM (
SELECT id,
status,
ts,
desired,
CASE
WHEN status = 'Off' THEN 0
WHEN status = lag(status, 1, null)
over (partition by id order by id, ts, status DESC)
THEN null
ELSE
1
end as tmp_desired
FROM stacko_64351844)
ORDER BY id, ts, status DESC);
RESULTS
ID STATUS TS DESIRED CALC_DESIRED
1 Off 0345 0 0
1 Charge 0400 1 1
1 Charge 0415 1 1
1 Off 0430 0 0
1 Charge 0445 2 2
1 Off 0500 0 0
1 Charge 0515 3 3
1 Charge 0530 3 3
1 Charge 0545 3 3
1 Charge 0600 3 3
1 Off 0615 0 0
我希望这会有所帮助...丰富
附言如果这个(或另一个)答案对您有帮助,请花点时间“接受”有帮助的答案 通过单击答案旁边的复选标记将其从“灰色”切换为“已填充”。
【讨论】:
【参考方案2】:MSSQL,但肯定/希望它能在 ansi 上运行。 感谢 Rich Murnane 提供数据提示
create TABLE #stacko_64351844 (
id int,
status varchar(20),
ts varchar(20),
desired int);
INSERT INTO #stacko_64351844
VALUES
(1, 'Off', '0345', 0),
(1, 'Charge', '0400', 1),
(1, 'Charge', '0415', 1),
(1, 'Off', '0430', 0),
(1, 'Charge', '0445', 2),
(1, 'Off', '0500', 0),
(1, 'Charge', '0515', 3),
(1, 'Charge', '0530', 3),
(1, 'Charge', '0545', 3),
(1, 'Charge', '0600', 3),
(1, 'Off', '0615', 0);
SELECT CASE status WHEN 'off' THEN 0
else SUM(CASE WHEN lg='off' THEN 1 ELSE 0 END) OVER(PARTITION BY id ORDER BY ts) END DesiredCalc
,t.id,t.status,t.ts,t.desired FROM (
SELECT LAG(status)OVER(PARTITION BY id ORDER BY ts)lg,* FROM #stacko_64351844
)t
ORDER BY ts
结果:
DesiredCalc id status ts desired
0 1 Off 0345 0
1 1 Charge 0400 1
1 1 Charge 0415 1
0 1 Off 0430 0
2 1 Charge 0445 2
0 1 Off 0500 0
3 1 Charge 0515 3
3 1 Charge 0530 3
3 1 Charge 0545 3
3 1 Charge 0600 3
0 1 Off 0615 0
【讨论】:
我在 CTE 上的一个分区中使用了 Lag 和 Lead。这是上述优秀解决方案的组合,加上马的重新标记。我会在我回来后发布我用过的东西!我在这里的第一篇文章,看到我不能说“谢谢”,所以...内容 = 1。以上是关于SQL迭代没有游标的行的主要内容,如果未能解决你的问题,请参考以下文章