我有下表:
id Prod_id Year Quartar Start_flag End_flag status
1 A001 2015 1 0 0 0
2 A001 2015 2 1 0 0
3 A001 2015 3 0 0 0
4 A001 2015 4 0 0 0
5 A001 2016 1 0 0 0
6 A001 2016 2 0 0 0
7 A001 2016 3 0 1 0
8 A001 2016 4 0 0 0
9 B002 2015 1 0 0 0
10 B002 2015 2 0 0 0
11 B002 2015 3 0 0 0
12 B002 2015 4 1 0 0
13 B002 2016 1 0 1 0
14 B002 2016 2 0 0 0
15 B002 2016 3 0 0 0
16 B002 2016 4 0 0 0
17 c003 2015 1 0 1 0
18 c003 2015 2 0 0 0
19 c003 2015 3 0 1 0
20 c003 2015 4 1 0 0
21 c003 2016 1 0 0 0
22 c003 2016 2 0 0 0
23 c003 2016 3 0 0 0
24 c003 2016 4 0 0 0
该表具有使用(Prod_id,Year,Quarter)的UNIQUE索引和在(Prod_id,Year,Quarter)上聚集的索引。 换句话说,表格是由 我的表具有以下内容:
我想在从start_flag到start_flag之后的第一个end_flag之前的四分之一的时间内,将状态列= 1更新。如果没有结束标记,则更新将一直持续到选定产品的最后记录。
实施更新后,更新后的表应如下所示:
id Prod_id Year Quartar Start_flag End_flag status
1 A001 2015 1 0 0 0
2 A001 2015 2 1 0 1
3 A001 2015 3 0 0 1
4 A001 2015 4 0 0 1
5 A001 2016 1 0 0 1
6 A001 2016 2 0 0 1
7 A001 2016 3 0 1 0
8 A001 2016 4 0 0 0
9 B002 2015 1 0 0 0
10 B002 2015 2 0 0 0
11 B002 2015 3 0 0 0
12 B002 2015 4 1 0 1
13 B002 2016 1 0 1 0
14 B002 2016 2 0 0 0
15 B002 2016 3 0 0 0
16 B002 2016 4 0 0 0
17 c003 2015 1 0 1 0
18 c003 2015 2 0 0 0
19 c003 2015 3 0 1 0
20 c003 2015 4 1 0 1
21 c003 2016 1 0 0 1
22 c003 2016 2 0 0 1
23 c003 2016 3 0 0 1
24 c003 2016 4 0 0 1
我已经使用pl / pgsql使用游标植入了一个解决方案,但是对于我来说,使用游标的解决方案需要30多个小时才能更新此列。 有没有使用游标进行此更新的替代方法? 我正在使用PostgreSQL 10.6。 请咨询并谢谢您。
答案 0 :(得分:0)
免责声明:我不太了解您的宿舍用例以及start_flag
范围在一段时间内的工作方式。因此,以下解决方案无需关注时间部分。如果您可以稍微说明一下时间示例,那么我可以肯定,以下解决方案只需要稍作调整(例如PARTITION
子句)即可为您工作。
我的样本数据:
id start_flag end_flag
1 0 0
2 1 0
3 0 0
4 0 0
5 0 1
6 0 0
7 1 0
8 0 1
9 0 0
10 0 1
11 0 0
12 0 1
13 1 0
14 0 0
16 0 0
查询:
SELECT
*,
GREATEST(
first_value(start_flag - end_flag) OVER (PARTITION BY sum ORDER BY id),
0
) as status
FROM (
SELECT
*,
SUM(start_flag + end_flag) OVER (ORDER BY id)
FROM mytable
) s
结果:
id start_flag end_flag status
1 0 0 0
2 1 0 1
3 0 0 1
4 0 0 1
5 0 1 0
6 0 0 0
7 1 0 1
8 0 1 0
9 0 0 0
10 0 1 0
11 0 0 0
12 0 1 0
13 1 0 1
14 0 0 1
16 0 0 1
说明:
SUM
或start_flag
)的累积end_flag
。这将创建组。在每个组中都存在相同的状态。 (请参见小提琴中的SUM
列)first_value
窗口功能:对于每个组,检查状态更改是由start_flag
(正)还是end_flag
(负)完成的。GREATEST()
将负值归一化为零。编辑:添加prod_id
和year/quarters
在所有用例中,总体来说都是安静的-仅使用窗口函数:
id
进行排序,而是按照year, quarter
进行排序prod_id
上)作为窗口函数:扩展查询:
SELECT
*,
GREATEST(
first_value(start_flag - end_flag) OVER (PARTITION BY prod_id, sum ORDER BY year, quarter),
0
) as status
FROM (
SELECT
*,
SUM(start_flag + end_flag) OVER (PARTITION BY prod_id ORDER BY year, quarter)
FROM mytable
) s