2014-09-30 2 views
0

У меня есть таблица sqlite, содержащая столбец имен файлов. Некоторые имена файлов являются дубликатами других файлов, поэтому я хотел бы перебирать каждую строку, искать столбцы для похожих записей и печатать эти результаты на консоли.Почему второй оператор SQL нарушает мой цикл?

A print(row[0]) указывает, что первая половина цикла findDupes работает, итерации по каждой строке. Вещи становятся странными, когда я делаю еще один оператор sqlite, чтобы найти похожие записи и распечатать вывод. Вместо того, чтобы продолжать цикл, цикл печатает только первую запись.

Я не эксперт по SQL, поэтому я не знаю, что я делаю неправильно. Любая помощь будет принята с благодарностью. Благодаря!

def getFiles(): 
    dirs = os.listdir(path) 
    for files in dirs: 
     c.execute('INSERT INTO myTable(files) VALUES(?)', (files,)) 

def findDupes(): 
    row = c.execute('select files from myTable order by files') 
    while True: 
     row = c.fetchone() 
     if row == None: 
      break 
     c.execute('select files from myTable where files like ?',(row[0]+'%',)) 
     dupe = c.fetchone() 
     print (dupe[0]) 
+0

Вы должны использовать новый курсор для вашего второго выбора. –

+0

Чтобы быть понятным, глядя на запрос, вы будете не только выбирать дубликаты, но и все, что имеет это имя в качестве префикса.Поэтому, если в вашей таблице есть как 'my_name', так и' my_name1', когда вы вызываете запрос 'select files from myTable, где такие файлы, как 'my_name%'' , вы вернете 'my_name1'. Я не знаю, какова цель вашего проекта, но вы должны знать об этом, чтобы не дать вам больше проблем. – JB333

ответ

2

Во-первых, ваш код не раскрывает, что c есть - это объект подключения или курсор? (либо можно использовать в этом объекте, но курсоры, как правило, предпочтительнее). И почему это глобально?

Предполагая, что это объект-курсор, то что происходит в первый раз через цикл, второй вызов c.execute сбрасывает запрос, поэтому второй раз вызывается c.fetchone, sqlite просматривает результаты select files from myTable where files like ?

Один из способов решения этой проблемы - использовать несколько курсоров; один для итерации над именами файлов и один для повторного поиска.

def findDupes(conn): #pass in your database connection object here 
    file_curs = conn.cursor() 
    file_curs.execute('select files from myTable order by files') 
    while True: 
     row = file_curs.fetchone() 
     if row == None: 
      break 
     dup_curs = conn.cursor() 
     dup_curs.execute('select files from myTable where files like ?',(row[0]+'%',)) 
     dupe = dup_curs.fetchone() 
     print (dupe[0]) 

Обратите внимание, что вы можете выполнять дедупликацию полностью в SQL (смотри, например, Deleting duplicate rows from sqlite database), но если вы новичок в SQL, вы можете придерживаться выше.

+0

Я предполагал, что 'c' был курсором, но из его вопроса и вашего ответа ясно, что это был объект соединения. +1 – aneroid

1

Ваша проблема в том, что в вашем цикле вы звоните row = c.fetchone() каждый раз, который будет возвращать одну строку из самого последнего выполнения запроса на с. На втором цикле это будут результаты c.execute('select files from myTable where files like ?',(row[0]+'%',)), причем одна строка уже выбрана (так что вы действительно устанавливаете row во второй результат c.execute('select files from myTable where files like ?',(row[0]+'%',)) с вашим текущим кодом, который, как я полагаю, вероятно, возвращается None и разбивает ваш цикл).

Попробуйте это:

def findDupes(): 
    c.execute('select files from myTable order by files') 
    rows = c.fetchall() 
    for row in rows: 
     c.execute('select files from myTable where files like ?',(row[0]+'%',)) 
     dupe = c.fetchone() 
     print (dupe[0]) 
+0

+1. Я печатаю слишком медленно на своем телефоне. – aneroid

1

Вам необходимо будет изменить способ использования c. При первом запуске цикла в findDupes() он отображает один ряд файлов. После этого у вас есть c.execute() для выбора типа нестандартного исполнения в той же итерации цикла. Когда происходит 2-я итерация, первый извлекает строку из вашего запроса типа «нет необходимости», а не исходный запрос по каждому файлу по порядку, который у вас был за пределами цикла.

Используйте другую переменную или курсор для двух запросов.

0

Вы можете решить эту проблему другим способом, указав для вас сервер базы данных. Таким образом, вы просто запустить один запрос, а неэффективный способ, запрашивая все файлы, а затем проверять каждый по одному:

def find_dupes(): 
    rows = c.execute('SELECT files, COUNT(*) FROM myTable GROUP BY files HAVING COUNT(*) > 1') 
    return [row[0] for row in rows] 

dupes = find_dupes() 
print('\n'.join(dupes)) 
+0

Основываясь на фактическом коде, результаты на самом деле будут отличаться от поиска точных дубликатов, это будут любые файлы, в которых в качестве префикса есть другой файл в таблице (см. Мой комментарий к основному вопросу выше). Но для чистого дублирования поиска я согласен, что ваше решение здорово! – JB333

Смежные вопросы