#python #pandas #postgresql
Вопрос:
У меня есть 2 таблицы в PostgreSQL:-
- «студенческий» стол
student_id name score
1 Adam 10
2 Brian 9
- таблица «student_log» :-
log_id student_id score
1 1 10
2 2 9
У меня есть скрипт на python, который извлекает фрейм данных со столбцами «имя» и «оценка», а затем заполняет его в таблице учащихся.
Я хочу обновлять таблицу student и student_log всякий раз, когда у студента меняется «оценка». Кроме того, если во фрейме данных есть новое имя учащегося, я хочу добавить для него еще одну строку в таблицу учащихся, а также сохранить ее запись в таблице «student_log». Кто-нибудь может подсказать, как это можно сделать?
Давайте рассмотрим новый извлеченный фрейм данных, который выглядит следующим образом:-
name score
Adam 7
Lee 5
Тогда ожидаемый результат будет:-
«студенческий» стол
student_id name score
1 Adam 7
2 Brian 9
3 Lee 5
таблица «student_log» :-
log_id student_id score
1 1 10
2 2 9
3 1 7
4 3 5
Ответ №1:
Наконец-то я нашел хороший ответ. Я использовал триггер, функцию и CTE.
Я создаю функцию для регистрации изменений вместе с триггером для обработки обновлений. Ниже приведен код.
CREATE OR REPLACE FUNCTION log_last_changes()
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS
$
DECLARE
serial_num integer;
BEGIN
IF NEW.name <> OLD.name OR NEW.score <> OLD.score
THEN
SELECT SETVAL('log_id_seq', (select max(id) from log)) into serial_num;
INSERT INTO log(student_id,score)
VALUES(NEW.id,NEW.score)
ON CONFLICT DO NOTHING;
END IF;
RETURN NEW;
END;
$;
CREATE TRIGGER log_student
AFTER UPDATE
ON student
FOR EACH ROW
EXECUTE PROCEDURE log_last_changes();
Выражение CTE выглядит следующим образом:-
WITH new_values(id, name, score) AS (
values
(1,'Adam',7),
(2,'Brian',9),
(3,'Lee',5)
),
upsert AS
(
UPDATE student s
SET NAME = nv.name,
SCORE = nv.score
FROM new_values nv, student s2
WHERE
s.id = nv.id and s.id = s2.id
Returning s.*
)
INSERT INTO student select id, name, score
FROM
new_values
WHERE NOT EXISTS (
SELECT 1 from upsert up where up.id=new_values.id
);
Ответ №2:
Я предполагаю, что вы пытаетесь различить два
кадра данных вот пример
#old student dataframe
old_pd:pd.DataFrame
#new student dataframe
new_pd:pd.DataFrame
joined_pd = new_pd.join(old_pd,on='name',lsuffix='_new',rsuffix='_old')
diff_pd = joined_pd[joined_pd['score_new']!=joined_pd['score_old']]
#then insert all diff_pd to student_log table.and update to student table
Комментарии:
1. Не могли бы вы, пожалуйста, подсказать, как это можно сделать непосредственно на PostgreSQL?
2. вы имеете в виду не использовать объединение фреймов данных.вместо прямого использования sql?
3. Да, используя Postgres напрямую.
4. при прямом использовании Postgres. Я рассмотрю возможность вставки новых данных во временную таблицу. затем используйте SQL-соединение,подзапрос, чтобы решить эту проблему