[英]Comparing CSV entries against entries in postgresql table using Python
我使用的是Postgresql 10,需要在CSV文件中進行查找,並將CSV文件中的條目與postgres表中的條目進行比較。 數據庫看起來像這樣,在這里我必須在domains表中插入域名,並在ranks表中進行排名:
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”
目前,我將域名插入域表,該域中的域ID會自動遞增並用作主鍵。 然后,我想將等級插入到等級表中。 但是我正在努力將domain_id從domains表獲取到ranks表中,因為domain_id用作ranks表中的外鍵。 因此,我想檢查域名的CSV文件,並根據domains表進行檢查,並在插入排名時獲取每個域的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連接到數據庫並進行查詢。
有誰知道如何做到這一點,或者對實現這一目標有其他建議?
您可以創建一個臨時表來保存CSV數據,並使用SQL查詢將數據插入domains
和ranks
表中。
這是臨時表的代碼:
CREATE TABLE temporary_table (
rank INTEGER,
domain TEXT
);
用CSV數據填充此表。
現在,插入CSV文件中存在但domains
表中不存在的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;
為了獲得我們要插入的排名的域ID,我們通過域名在temporary_table
表和domains
表之間進行了連接。 這樣,我們可以找到每個等級的domain_id。
請注意,我在列插入中添加了1作為list_id
和now()::date
,因為您沒有提供應該從中提取數據的列。
另外,請小心組合主鍵PRIMARY KEY (list_id, rank, date)
。 如果要在同一日期為多個域插入等級,並且某些域具有相同的rank和list_id值,則將得到重復的鍵值錯誤,並且不會插入數據。 為了解決此問題,您也可以在組合的主鍵中添加domain_id。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.