Как сравнить между двумя источниками данных в Python - PullRequest
0 голосов
/ 21 октября 2018

У меня есть большие наборы данных из 2 источников, один - огромный текстовый файл (как новые данные), а другой - из базы данных (MySQL) (как исторические данные).Как их сравнить, чтобы выяснить различия (получить только новые и измененные записи).Я намеревался прочитать каждую строку в текстовом файле и сравнить с данными в MySQL.

Текстовый файл (demo.txt):

0001|NAME1|A1
0002|NAME2|A2
0003|NAME3|A3
0004|NAME4|A4
0005|NAME5|A1

Данные в MySQL:

id   |   name   |   address
----------------------------
0001 |   NAME1  |   A1
----------------------------
0002 |   NAME2  |   A2
----------------------------
0003 |   NAME3  |   A4
----------------------------
0004 |   NAME4  |   A4
----------------------------

Ожидаемый результат:

0003|NAME3|A4
0005|NAME5|A1

И это мое усилие:

connection = pymysql.connect(host='localhost',
                             user='root',
                             password='password',
                             db='test',
                             charset='utf8',
                             cursorclass=pymysql.cursors.DictCursor)
cursor = connection.cursor()
myfile = open("demo.txt","r")
lines = myfile.readlines()
for line in lines:
    data=line.split('|')
    sql_query = """SELECT * FROM HistoricalTable WHERE id = {}""".format(data[0])
    check=cursor.execute(sql_query)
    result=cursor.fetchall()

    if check>=1:
        for i in result:
            if data[0]==i['id'] and data[1]==i['name'] and data[2]==i['address']:
                print("Ignore")
            else:
                print(line)
                break
    else:
        print(line)

И я знаю, что это не самый лучший способ и займет многовремя!Так что, пожалуйста, можно мне что-нибудь предложить?

1 Ответ

0 голосов
/ 21 октября 2018

Ваши вопросы

Я могу выделить два вопроса: - Проблема оптимизации, - Технический вопрос о сравнении наборов данных.

Об оптимизации

Лучше всегоесть рабочая программа, чем оптимизированная, которая не работает идеально.Таким образом, вы можете сосредоточиться на разработке чего-то функционального, а затем оптимизировать его.

В любом случае, если вы хотите найти дубликаты в двух наборах данных, вам понадобится по крайней мере один набор данных в памяти, если ваши наборы данных не имеют некоторыхвнутренние свойства, которые позволяют дальнейшую оптимизацию (например, я думаю о порядке).

О поиске дубликатов

Например, меньший набор данных может быть загружен в повторяемый (например, list), а второй можно итерировать из файла / базы данных, используя функцию генератора.

Вот демонстрационная версия:

# data1 in memory
data1 = ['a', 'b', 'd', 'c']


# data2 produced by a generator
def item_data2():
    for item in ['a', 'd', 'e', 'c']:
        yield item


duplicates = [x for x in item_data2() if x in data1]
# -> ['a', 'd', 'c']

Некоторые рекомендации

Чтение файла CSV

Чтобы прочитать файлы CSV, вы можете использовать библиотеку csv .В вашем конкретном случае вы можете использовать DictReader .

import csv
import io
import os
import pprint

delimiter = '|'
header = "id|name|address".split(delimiter)

data_dir = "path/to/data/directory"

csv_path = os.path.join(data_dir, "source1.csv")

with io.open(csv_path, mode="r", encoding="utf-8") as f:
    reader = csv.DictReader(f, header, delimiter=delimiter)
    for entry in reader:
        pprint.pprint(entry)

# ->
# OrderedDict([('id', '0001'), ('name', 'NAME1'), ('address', 'A1')])
# OrderedDict([('id', '0002'), ('name', 'NAME2'), ('address', 'A2')])
# OrderedDict([('id', '0003'), ('name', 'NAME3'), ('address', 'A3')])
# OrderedDict([('id', '0004'), ('name', 'NAME4'), ('address', 'A4')])
# OrderedDict([('id', '0005'), ('name', 'NAME5'), ('address', 'A1')])

Индексирование записей по id

Если вы хотите сравнить данные, которые имеюттот же id , вы можете хранить данные в отображении, которое связывает id и другие файлы:

data_mapping = {}
with io.open(csv_path, mode="r", encoding="utf-8") as f:
    reader = csv.DictReader(f, header, delimiter=delimiter)
    for entry in reader:
        data_id = entry.pop('id')
        data_mapping[data_id] = entry

Запрос к базе данных

Для базы данных вы можете перебирать каждую запись вместо выборки всех записей: вместо этого вы можете использовать fetchone.Но, на самом деле, вы можете использовать курсор в качестве итератора.

Вот пример:

import pymysql


connection = pymysql.connect(host='localhost',
                             user='root',
                             password='password',
                             db='test',
                             charset='utf8',
                             cursorclass=pymysql.cursors.DictCursor)

try:
    with connection.cursor() as cursor:
        # Using the cursor as iterator
        cursor.execute("SELECT * FROM HistoricalTable")
        for row in cursor:
            print(row)
finally:
    connection.close()
...