![](/img/trans.png)
[英]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.