我正在使用Postgresql 10,我需要在CSV文件中进行查找,并将CSV文件中的条目与postgres表中的条目进行比较。数据库看起来像这样,我必须在域表中插入域名并在rank表中排名:
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表中获取到rank表中,因为domain_id在rank表中充当外键。所以我想检查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连接数据库并进行查询。
有谁知道如何做到这一点,或者对如何实现这一点有任何其他建议?
答案 0 :(得分:1)
您可以创建一个临时表来保存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;
为了获取我们要插入的排名的域ID,我们按域名在temporary_table
和domains
表之间进行连接。这样,我们就可以找到每个等级的domain_id。
请注意,我在排名插入中添加了1 list_id
和now()::date
,因为您没有提供应从中提取数据的列。
另外,请注意组合的主键PRIMARY KEY (list_id, rank, date)
。
如果要在同一日期插入多个域的排名,并且某些域具有相同的rank和list_id值,则会出现重复的键值错误,并且不会插入数据。
为了解决这个问题,您还可以在组合主键中添加domain_id。