[英]Combining multiple 'AND' with 'LIKE' statements in PostgreSQL
[英]postgresql multiple statements in for loop
我需要编写一个postgressql函数来处理一些时间序列数据,我想遍历每个时间步长并确定是否需要更新未来几个时间步长中的值,并且它将是更新后的值当循环迭代到以下时间步长时,将应用决策。 我希望我已经清楚地解释了。
因此,例如表:
CREATE TEMPORARY TABLE datatable (
unixdatetime integer,
value integer,
);
INSERT INTO datatable (unixdatetime, value) VALUES
(1,56),
(2,23),
(3,7),
(4,68),
(5,31),
(6,42);
我尝试将以下for循环应用于它:
FOR r IN
SELECT * FROM datatable
LOOP
DROP TABLE IF EXISTS currentdata;
CREATE TEMPORARY TABLE currentdata AS (
SELECT dt.unixdatetime as currentTime,
lead(dt.unixdatetime,1) OVER (ORDER BY dt.unixdatetime) AS lead1stTime,
dt.value AS currentValue,
lead(dt.value,1) OVER (ORDER BY dt.unixdatetime) AS lead1stVal
FROM datatable dt
);
_counter = 0;
IF (SELECT currentValue%2 FROM currentdata) = 1
THEN _counter = _counter + 1;
END IF;
IF (SELECT lead1stVal%2 FROM currentdata) = 1
THEN _counter = _counter + 1;
END IF;
UPDATE datatable dt
SET value = (CASE WHEN _counter = 2 AND cd.currentValue <> 888 THEN 999
ELSE cd.currentValue
END)
FROM currentdata cd
WHERE dt.unixdatetime = cd.currentTime;
UPDATE datatable dt
SET value = (CASE WHEN _counter = 2 THEN 888
ELSE cd.lead1stVal
END)
FROM currentdata cd
WHERE dt.unixdatetime = cd.lead1stTime;
END LOOP;
我的预期结果将是:
| unixdatetime | Value |
| 1 | 56 |
| 2 | 999 |
| 3 | 888 |
| 4 | 68 |
| 5 | 31 |
| 6 | 42 |
大家都知道,我仍然无法切换到Postgresql思维模式,并且仍然尝试使用python和C ++等在postgressql中不起作用的语言的技巧。 我注意到的是:
循环中的每个语句都将在整个表上执行,然后再移至循环中的下一条语句。 而是依次执行所有语句,然后再迭代到表的行。
由于1。,_ counter不能提供与其他语言的for循环相同的效果。 我确实需要for循环中的计数器,因为实际任务需要我提前2个时间步长查看值。
变通办法的任何有用建议,将不胜感激。
提前致谢,
杰森
您可以使用以下语句检索所需的内容,而无需循环。
select unixdatetime, value,
case
when is_odd and next_is_odd then 999
when is_odd and prev_is_odd then 888
else value
end as new_value
from (
select unixdatetime, value,
value % 2 <> 0 as is_odd,
coalesce(lag(value) over (order by unixdatetime) % 2 <> 0, false) as prev_is_odd,
coalesce(lead(value) over (order by unixdatetime) % 2 <> 0, false) as next_is_odd
from datatable
) t
order by unixdatetime;
现在,可以用一个语句直接更新整个表:
update datatable
set value = nv.new_value
from (
select unixdatetime, value,
case
when is_odd and next_is_odd then 999
when is_odd and prev_is_odd then 888
else value
end as new_value
from (
select unixdatetime, value,
value % 2 <> 0 as is_odd,
coalesce(lag(value) over (order by unixdatetime) % 2 <> 0, false) as prev_is_odd,
coalesce(lead(value) over (order by unixdatetime) % 2 <> 0, false) as next_is_odd
from datatable
) t
) nv
where nv.unixdatetime = datatable.unixdatetime
and nv.new_value <> datatable.value; -- only update those that changed
SQLFiddle示例: http ://sqlfiddle.com/#!15/128d9/1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.