Esporta singolo dataframe panda in più tabelle SQL (normalizzazione automatica)

Sep 02 2020

Ho un DataFrame come questo, ma con milioni di righe e circa 15 colonne:

       id    name  col1   col2  total
0 8252552 CHARLIE DESC1 VALUE1   5.99
1 8252552 CHARLIE DESC1 VALUE2  20.00
2 5699881    JOHN DESC1 VALUE1  39.00
2 5699881    JOHN DESC2 VALUE3  -3.99

Il DataFrame deve essere esportato in un database SQL, in diverse tabelle. Attualmente sto usando SQLite3, per testare la funzionalità. Le tabelle sarebbero:

  • principale ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, people_id INTEGER, col1_id INTEGER, col2_id INTEGER, total REAL)
  • persone ( id INTEGER NOT NULL PRIMARY KEY UNIQUE, name TEXT UNIQUE)
  • col1 ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT UNIQUE)
  • col2 ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT UNIQUE)

La tabella principale dovrebbe essere simile a questa:

  people_id col1_id col2_id  total
0   8252552       1       1   5.99
1   8252552       1       2  20.00
2   5699881       1       1  39.00
3   5699881       2       3  -3.99

Altre tabelle, come "persone", come questa:

     id    name
8252552 CHARLIE
5699881    JOHN

Il fatto è che non riesco a trovare come ottenerlo utilizzando l' schemaattributo del to_sqlmetodo nei panda. Usando Python, farei qualcosa del genere:

conn = sqlite3.connect("main.db")
cur = conn.cursor()
for row in dataframe:
    id = row["ID"]
    name = row["Name"]
    col1 = row["col1"]
    col2 = row["col2"]
    total = row["total"]
    cur.execute("INSERT OR IGNORE INTO people (id, name) VALUES (?, ?)", (id, name))
    people_id = cur.fetchone()[0]
    cur.execute("INSERT OR IGNORE INTO col1 (col1) VALUES (?)", (col1, ))
    col1_id = cur.fetchone()[0]
    cur.execute("INSERT OR IGNORE INTO col1 (col2) VALUES (?)", (col2, ))
    col2_id = cur.fetchone()[0]
    cur.execute("INSERT OR REPLACE INTO main (people_id, col1_id, col2_id, total) VALUES (?, ?, ?, ?)", (people_id, col1_id, col2_id, total ))
conn.commit()

Ciò aggiungerebbe automaticamente i valori corrispondenti alle tabelle (persone, col1 e col2), creerebbe una riga con i valori desiderati e le chiavi esterne e aggiungerebbe quella riga alla tabella primaria. Tuttavia, ci sono molte colonne e righe e questo potrebbe essere molto lento. Inoltre, non sono molto sicuro che questa sia una "best practice" quando si tratta di database (sono abbastanza nuovo nello sviluppo di database)

La mia domanda è: c'è un modo per esportare un DataFrame panda su più tabelle SQL, impostando le regole di normalizzazione, come nell'esempio sopra? C'è un modo per ottenere lo stesso risultato, con prestazioni migliorate?

Risposte

1 Bugface Sep 02 2020 at 08:26

Potresti prima dividere il frame di dati di Panda in diversi frame di dati secondari in base alle tabelle del database, quindi applicare il to_sql()metodo su ciascun frame di dati secondario?