Обновление таблицы на основе значений из предыдущей строки - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть таблица, и я хочу обновить значения в таблице на основе значений из предыдущей строки.Здесь я хочу обновить «Значение» в виде суммы предыдущей строки Значение + Настройка.Я хотел бы сделать это в 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 голосов
/ 13 декабря 2018

Если вы используете последнюю версию 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    
0 голосов
/ 13 декабря 2018

Один из вариантов - загрузить его в pandas DataFrame через .read_sql(), вычислить значения следующих ячеек Value и сбросить обратно в SQLite через .to_sql(), что-то вроде этого:

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 - таблица будет отброшена перед вставкой новых строк.

...