Сравнение записей CSV с записями в таблице postgresql с использованием Python - PullRequest
0 голосов
/ 06 мая 2018

Я использую Postgresql 10, и мне нужно выполнить поиск в файле CSV и сравнить записи в файле CSV с записями в моей таблице postgres. База данных выглядит следующим образом, где я должен вставить имя домена в таблицу доменов и ранги в таблице рангов:

CREATE TABLE lists (list_id integer PRIMARY KEY,
                    list_name text);

CREATE TABLE domains (domain_id BIGSERIAL PRIMARY KEY,
                      domain_name text UNIQUE);

CREATE TABLE ranks (list_id integer REFERENCES lists,
                    domain_id integer REFERENCES domains,
                    rank integer,
                    date date,
                    PRIMARY KEY (list_id, rank, date));

CSV содержит две записи: ранг и имя домена, например: «1, google.com»

В настоящее время я вставляю имена доменов в таблицу доменов, где идентификатор домена автоматически увеличивается и служит первичным ключом. Затем я хочу вставить ранги в таблицу рангов. Но я изо всех сил пытаюсь получить domain_id из таблицы доменов в таблицу рангов, поскольку domain_id служит внешним ключом в таблице рангов. Поэтому я хочу проверить CSV для доменного имени, проверить его по таблице доменов и получить domain_id для каждого домена, когда я вставляю ранги. Таким образом, каждое доменное имя может иметь несколько рангов, это различается по дате.

Текущий скрипт, который я сейчас использую, выглядит следующим образом:

    import tkinter as tk
    from tkinter import filedialog
    import csv
    import psycopg2
    import shutil as sh

    root = tk.Tk()
    root.withdraw()
    file_path = filedialog.askopenfilename()
    new_path = 'C:/Users/%user%/Desktop/alexa-top1m_16042018.csv'

    conn = psycopg2.connect("host=localhost dbname=test user=postgres   password=test")
    cur = conn.cursor()

    sh.copy2(file_path, new_path)
    with open(new_path, 'r') as original: data = original.read()
    with open(new_path, 'w') as modified: modified.write("rank,domain_name\n" + data)

    with open(new_path, 'r') as f:
        reader = csv.DictReader(f)


    for row in reader:
        cur.execute(
           """INSERT INTO ranks (list_id, rank, date) VALUES (%s, %s, %s);""", ( 1, row['rank'], '2018-04-16',)
        )

   conn.commit()

Я использую psycopg2 для подключения к БД и выполнения запросов.

Кто-нибудь знает, как это сделать, или есть какие-либо другие предложения о том, как этого добиться?

1 Ответ

0 голосов
/ 06 мая 2018

Вы можете создать временную таблицу, в которой будут храниться данные CSV, и использовать запросы SQL для вставки данных в таблицы domains и ranks.

Вот код для временной таблицы:

CREATE TABLE temporary_table (
  rank INTEGER,
  domain TEXT
);

Заполните эту таблицу данными CSV.

Теперь вставьте домены, которые присутствуют в файле CSV, но отсутствуют в таблице domains.

INSERT INTO domains (domain_name)
  (SELECT DISTINCT domain as domain_name FROM temporary_table
    EXCEPT
  SELECT domain_name FROM domains);

Теперь, когда у вас есть все существующие домены в таблице domains, мы можем вставить строки в таблицу ranks.

INSERT INTO ranks (list_id, domain_id, rank, date)
    SELECT 1 as list_id, d.domain_id, rank, now()::DATE 
    FROM temporary_table tt JOIN domains d ON tt.domain = d.domain_name;

Чтобы получить идентификатор домена для вставляемого нами ранга, мы выполняем соединение между таблицей temporary_table и domains по имени домена. Таким образом, мы можем найти domain_id для каждого ранга.

Обратите внимание, что я добавил 1 как list_id и now()::date во вставке рангов, потому что вы не указали столбцы, из которых эти данные должны быть извлечены.

Также будьте осторожны с комбинированным первичным ключом PRIMARY KEY (list_id, rank, date). Если вы хотите вставить ранги для нескольких доменов в одну и ту же дату, и некоторые из доменов имеют одинаковые значения rank и list_id, вы получите ошибку дублированного значения ключа, и данные не будут вставлены. Чтобы это исправить, вы также можете добавить domain_id в комбинированный первичный ключ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...