Usuwanie duplikatów z bazy MySQL w Pythonie

0

Witam, mam problem z moim programem którego zadaniem jest zarządzanie bazą pojazdów i ich właścicieli. W programie łączę się z bazą MySQL i pobieram tabelę "baza" która zawiera kolumny: ID, Imie, Nazwisko, Wiek, Kod_pocztowy, Miasto, Ulica, Nr_mieszkania, Marka, Model, Nr_rejestracji . Wszystko działa poprawnie poza metodą "remove_duplicates", po naciśnięciu odpowiedniego przycisku nic się nie dzieje, terminal nie zwraca żadnego błędu. Poniżej załączam kod z niedziałającą metodą oraz screen z okna programu. Z góry dziękuję za pomoc.

def remove_duplicates():
    query = "DELETE t1 FROM baza t1 INNER JOIN baza t2 WHERE t1.ID > t2.ID AND t1.Nr_rejestracji = t2.Nr_rejestracji"
    cursor.execute(query)
    mydb.commit()
    clear()

problem.jpg

1

Usuwasz te elementy, które mają ten sam numer rejestracyjny i wyższe ID od istniejącego już w tabeli.
Te Twoje duplikaty na screenie mają ten sam nr rej., i ID również, co jest trochę dziwne, zazwyczaj ID powinno być PK, więc unikalne.
Chyba, że jeden pracownik może mieć więcej taksówek niż 1, to dane pracownika do jednej tabeli, dane taksówek do drugiej i powiązanie taksówki do pracownika przez ID Pracownika.

1

@dominox71: Moim zdaniem w ogóle nie powinno być sytuacji, że są jakieś duplikaty. Sama baza powinna tego pilnować. Wydaje mi się, że powinieneś jeszcze raz przemyśleć schemat.

Wracając do pytania, co to znaczy że nic się nie dzieje? Chodzi o to, że z bazy się nie usuwają wartości? Bo na konsoli nic ci się nie wypisze, bo nie wypisujesz.

0

Zakładam, że PK jest unikalne ale duplikaty się pytaczowi pewnie pojawiły ze względu złączenie z inną tabelą. Ciężko coś więcej powiedzieć bez dokładnej struktury i zapytania.

2

Dodam jeszcze, że dobrą strategią przy tego typu operacjach jest stworzyć najpierw zapytanie zwracające rekordy, które chcemy usunąć. Zobacz sobie co zwraca zapytanie:

select * FROM baza t1 INNER JOIN baza t2 WHERE t1.ID > t2.ID AND t1.Nr_rejestracji = t2.Nr_rejestracji

Masz w ten sposób informacje o tym ile i jakie wiersze usunie Ci operacja DELETE.
Możesz ją wykorzystać też w aplikacji. Po kliknięciu na "usuń duplikaty" możesz informować użytkownika o ilości wierszy do usunięcia, a także o tym jakie to wiersze, możesz też się wtedy zapytać czy na pewno chce wykonać tę operację.

0

Skoro problemem są duble powstałe przy imporcie, to możesz też już przy samym wykonywaniu importu pomijać duble. Lub jeżeli już naprawdę się upierasz na wpisy z identycznymi ID, możesz wybrać inną metodę kasowania dubli, ta z tabelą pośrednią jest w takim przypadku idealna dla Ciebie. Musisz jednak zdawać sobie sprawę z tego jakie niesie za sobą zagrożenia - jeśli w przyszłości utworzysz powiązania z innymi tabelami lub będziesz wykorzystywał tę tabelę w procedurach/widokach to próba usunięcia takiej tabeli wywoła błąd przy włączonym sprawdzaniu kluczy obcych.

0
Dregorio napisał(a):

@dominox71: Moim zdaniem w ogóle nie powinno być sytuacji, że są jakieś duplikaty. Sama baza powinna tego pilnować. Wydaje mi się, że powinieneś jeszcze raz przemyśleć schemat.

Dokładnie.

Ja bym "bazę" przeznaczył na zaoranie, a dane unikalne jednorazowo skopiował do dobrze zaprojektowanej bazy (**zestawu **tabel).
Takie kopiowania (z selekcją unikalności) ja piszę prawie intuicyjnie, wydają mi się łatwiejsze niż korekty "na oryginale".

O jakości projektu świadczy już genialna nazwa tabeli "baza" - to tak jakby zmienną nazwać "zmienna"

0

Uparłem się jednak przy moim rozwiązaniu i zmodyfikowałem funkcję dodawania danych oraz funkcję zapisującą dane do pliku. Projekt był projektem zaliczeniowym i miałem narzucone odgórnie, że ID ma być nadawane przez użytkownika programu, jak na pierwszą styczność z MySQL myślę, że wyszło całkiem nieźle :) Dla ciekawskich poniżej zamieszczam zmodyfikowane funkcje opisane powyżej:


def getrow(event):
trv.identify_row(event.y)
item = trv.item(trv.focus())
t1.set(item['values'][0])
t2.set(item['values'][1])
t3.set(item['values'][2])
t4.set(item['values'][3])
t5.set(item['values'][4])
t6.set(item['values'][5])
t7.set(item['values'][6])
t8.set(item['values'][7])
t9.set(item['values'][8])
t10.set(item['values'][9])
t11.set(item['values'][10])
def dodaj():
id = t1.get()
imie = t2.get()
nazwisko = t3.get()
wiek = t4.get()
kod = t5.get()
miasto = t6.get()
ulica = t7.get()
nr_m = t8.get()
marka = t9.get()
model = t10.get()
nr_rej = t11.get()
check=0

for i in dane:
    if i[0]==int(id):
        check=1
if check==1:
    messagebox.showerror("Zduplikowano", "Pracowinik o podanym id już istnieje!")
    return False
else:
    query = "INSERT INTO baza(ID, Imie, Nazwisko, Wiek, Kod_pocztowy, Miasto, Ulica, Nr_mieszkania, Marka, " \
            "Model, Nr_rejestracji) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
    cursor.execute(query, (id, imie, nazwisko, wiek, kod, miasto, ulica, nr_m, marka, model, nr_rej))
    mydb.commit()
    anuluj()
    return False
def savedb():
if messagebox.askyesno("Potwierdź.", "Czy na pewno chcesz zapisać dane do bazy?"):
numery = pd.read_sql('SELECT ID FROM baza', con=mydb)
df = pd.DataFrame(numery)
nump = df["ID"].to_numpy()
x = nump.tolist()
update(dane)
l_pow=0
for i in x:
for j in dane:
if i==int(j[0]):
dane.remove(j)
l_pow+=1
l_uni=len(dane)
if len(dane)==0:
messagebox.showerror("Brak danych.", "Brak nowych indeksów do dodania!")
return False
else:
for i in dane:
id = i[0]
imie = i[1]
nazwisko = i[2]
wiek = i[3]
kod = i[4]
miasto = i[5]
ulica = i[6]
nr_m = i[7]
marka = i[8]
model = i[9]
nr_rej = i[10]
query = "INSERT INTO baza(ID, Imie, Nazwisko, Wiek, Kod_pocztowy, Miasto, Ulica, Nr_mieszkania, " \
"Marka, Model, Nr_rejestracji) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
cursor.execute(query, (id, imie, nazwisko, wiek, kod, miasto, ulica, nr_m, marka, model, nr_rej))
mydb.commit()
anuluj()
messagebox.showinfo("Dane zapisano.", "Dane zostały pomyślnie zapisane do bazy.\nIlość rekordów które nie zostały zapisane: "+str(l_pow)+"\nIlość dodanych rekordów: "+str(l_uni))
else:
return False

1 użytkowników online, w tym zalogowanych: 0, gości: 1