根据上一行中的值更新表

时间:2018-12-12 22:23:59

标签: python sql sqlite rdbms

我有一个表,我想根据上一行中的值更新表中的值。在这里,我想将“值”更新为上一行“值+调整”的总和。我想在SQLite中做到这一点。

原始表

Name  | Value | Adjustment 
Apple |  10   | 5
Ball  |  20   | 10
Cat   |  30   | 15
Dog   |  40   | 0
Emily |  50   | 10
Frog  |  60   | 0
Goat  |  70   | 5

更新表

Name  | Value       | Adjustment 
Apple |  10         | 5
Ball  |  15 (10+5)  | 10
Cat   |  25 (15+10) | 15
Dog   |  40 (25+15) | 0
Emily |  40 (40+0)  | 10
Frog  |  50 (40+10) | 0
Goat  |  50 (50+0)  | 5

我可以使用python做到这一点,但我想知道在SQLite中是否有快速有效的方法。

2 个答案:

答案 0 :(得分:1)

如果您使用的是最新版本的sqlite(3.25或更高版本),则使用窗口功能非常容易。以下假设您正在按名称列进行排序,如示例输入和输出中所示:

CREATE TABLE example(name TEXT, value INTEGER, adj INTEGER);
INSERT INTO example VALUES('Apple',10,5);
INSERT INTO example VALUES('Ball',20,10);
INSERT INTO example VALUES('Cat',30,15);
INSERT INTO example VALUES('Dog',40,0);
INSERT INTO example VALUES('Emily',50,10);
INSERT INTO example VALUES('Frog',60,0);
INSERT INTO example VALUES('Goat',70,5);
CREATE INDEX example_idx_name ON example(name); -- Used in the window ordering
SELECT name AS "Name"
     , first_value(value) OVER names + sum(adj) OVER names - adj AS "Value"
     , adj AS "Adjustment"
FROM example
WINDOW names AS (ORDER BY name)
ORDER BY name;

产生:

Name        Value       Adjustment       
----------  ----------  ----------
Apple       10          5         
Ball        15          10        
Cat         25          15        
Dog         40          0         
Emily       40          10        
Frog        50          0         
Goat        50          5

现在,要改为更新表... UPDATE的问题在于行以任意顺序更新(可能是按rowid进行的,但您不应该依赖这样的实现细节),因此可以确实不是基于“上一个”行来做某事。一种方法:使用上述查询的版本来填充临时表,然后使用该表来更新原始表:

CREATE TEMP TABLE staging(id INTEGER PRIMARY KEY, value INTEGER);
INSERT INTO staging
    SELECT rowid, first_value(value) OVER names + sum(adj) OVER names - adj
    FROM example WINDOW names AS (ORDER BY name);
UPDATE example AS e SET value = (SELECT value FROM staging AS s WHERE s.id = e.rowid);
DROP TABLE staging;
SELECT * FROM example ORDER BY name;
name        value       adj       
----------  ----------  ----------
Apple       10          5         
Ball        15          10        
Cat         25          15        
Dog         40          0         
Emily       40          10        
Frog        50          0         
Goat        50          5    

答案 1 :(得分:0)

一种选择是通过.read_sql()将其加载到pandas DataFrame中,计算下一个Value单元格值,然后通过.to_sql()转储到SQLite中。行:

import sqlite3
import pandas as pd

conn = sqlite3.connect(...)

df = pd.read_sql_table(name_of_table, conn)

for i in range(1, len(df)):
    df.iloc[i, 1] = df.iloc[i - 1, 1] + df.iloc[i - 1, 2]

df.to_sql(name=name_of_table, con=conn, if_exists='replace', index=False)

请注意"replace" if_exists的行为-它将在插入新行之前删除表。