2015-08-07 19 views
9

Abbiamo un database piuttosto antiquato che contiene un gran numero di individui insieme a una serie di risultati che hanno completato. Storicamente si è fatto poco per scoraggiare i dati individuali duplicati, quindi siamo finiti in una situazione in cui i nostri dati sono piuttosto sporchi. Una versione estremamente semplificata di questo può essere trovato here.Schema di schema dello schema del database per i dati che si fondono

Ora stiamo ridisegnando lo schema e l'interfaccia utente. Forniremo all'utente uno strumento per unire le persone. Nell'esempio fornito, Dave e David sono chiaramente la stessa persona e hanno raggiunto 4 risultati in totale.

Dato che gli utenti commettono errori e che sono coinvolte molte più tabelle rispetto all'esempio, sto cercando un modello di schema che faciliti la fusione dei dati e, in particolare, lo smantellamento dei dati se (quando!) l'utente fa inevitabilmente un errore.

Gli elenchi collegati di qualche tipo sembrano essere una soluzione ma non sono esattamente efficienti per questo caso d'uso. Ci sono altri concetti che potrebbero prestarsi a questa situazione? Eventuali modelli di progettazione specifici che potrebbero essere appropriati?

Edit: come si sta piuttosto traballante SQLFiddle oggi ecco il creare/inserire/select sql che era sul sqlfiddle:

CREATE TABLE individual 
    (`individual_id` int, `forename` varchar(50), `surname` varchar(50)) 
; 

CREATE TABLE achievement 
    (`achievement_id` int, `name` varchar(50), `description` varchar(50)) 
; 

CREATE TABLE individual_achievement 
    (`individual_id` int,`achievement_id` int) 
; 

INSERT INTO individual 
    (`individual_id`, `forename`, `surname`) 
VALUES 
    (1, 'Dave', 'Deane'), 
    (2, 'David', 'Deane') 
; 

INSERT INTO achievement 
    (`achievement_id`, `name`, `description`) 
VALUES 
    (1, 'unit_1', 'Unit 1'), 
    (2, 'unit_2', 'Unit 2'), 
    (3, 'unit_3', 'Unit 3'), 
    (4, 'unit_4', 'Unit 4') 
; 

INSERT INTO individual_achievement 
    (`individual_id`,`achievement_id`) 
VALUES 
    (1, 1), 
    (1, 3), 
    (2, 2), 
    (2, 4) 
; 

select * from individual i 
join individual_achievement ai using (individual_id) 
join achievement a using (achievement_id) 

Edit 2: appena trovato questo very similar question, sperando in 4 anni lì potrebbe anche altre soluzioni.

+0

Impossibile vedere SQLFiddle, ma perché non si fondono automaticamente gli obiettivi piuttosto che gli utenti di lettere lo fanno? – plalx

+0

Domanda ragionevole @plalx.Non abbiamo abbastanza informazioni a nostra disposizione per poter rilevare in modo affidabile i duplicati. Ci sono molti casi in cui abbiamo solo nomi e cognomi su cui non è assolutamente sufficiente. in molti casi abbiamo una data di nascita, ma anche in questo caso esiste la possibilità che ciò sia sbagliato. Il nostro piano è quello di evidenziare all'utente quelli che pensiamo potrebbero essere duplicati, ma solo l'utente saprà con certezza se i suoi individui sono duplicati o meno. –

risposta

4

Ecco una tattica che è possibile utilizzare.

Innanzitutto, creare una nuova tabella, per ora chiamarla "Individual_v2", con le stesse colonne identiche alla tabella originale Individuale. (Idealmente, alla fine si sostituirà Individual con questa tabella: realisticamente, le persone potrebbero ancora inserire dati in Individual, e dovrai "pulire" i dati spostandoli o unendoli in Individual_v2.) Configura questa tabella con i link a Achievement. (Per ora, sto assumendo Achievement è pulito.)

Quindi, creare una tabella “Mappatura” in questo modo:

IndividualMapping 

OldIndividual_Id 
NewIndividual_Id 
CreatedAt 
CreatedBy 
ApprovedAt -- Nullable! 
ApprovedBy -- Nullable! 

Le colonne “creato” vengono utilizzati per determinare quando e da chi (o cosa) è stata creata la mappatura.

Le colonne "Approvato" vengono utilizzate per determinare se i dati sono stati migrati alle nuove tabelle.

Per ogni "vecchio" elemento, si determina dove potrebbe mappare nella "nuova" tabella; se esegue il mapping su nessun elemento esistente, crearne uno nella nuova tabella.

Quindi, aggiungere una voce nella tabella di mappatura. Se è stato creato un nuovo articolo, contrassegnarlo come approvato; se la fiducia è alta, contrassegnala come approvata; altrimenti, lascialo "non approvato" e in attesa di revisione. A tempo debito un revisore esaminerà le cose e approverà la mappatura, modificherà la mappatura su un nuovo elemento esistente esistente o creerà un altro nuovo oggetto e mapperà ad esso.

Una volta completato, il lavoro "reale" viene eseguito sulla nuova tabella. La vecchia tabella e la tabella di mapping possono essere utilizzate per identificare da dove provengono i nuovi dati e, se necessario, per annullare/modificare i mapping.

Qui ci sono un sacco di problemi di implementazione e supporto senza risposta qui, e nel complesso sembra strano come diamine.A lungo termine, una volta risolto il problema dei dati duplicati, puoi eliminare la tabella precedente (e di mappatura), ma fino a quel momento avresti un sistema esigente.


addenda

Sono un po 'a parlare attraverso le cose qui, senza entrare in un'analisi esaustiva. Il sistema che penso tu stia descrivendo sarà pignolo e concettualmente complesso con cui lavorare, anche se le tabelle sono relativamente semplici e i dettagli finali non rientrano nell'ambito di una domanda dell'SO. Troppo, molto dipende da quali sono gli obiettivi generali del sistema e la sua riprogettazione. Ho intenzione di fare alcune ipotesi qui:

  • Il sistema “esistente” rimarrà al suo posto

  • Gli individui (e le loro premi) in modo inseriti deve essere fatta immediatamente disponibili, come lo sono sempre stati .

  • I duplicati continueranno a essere immessi; se, quando e come fattibile, essi devono essere “consolidato” con le voci preesistenti

fatto in questo modo, il sistema avrebbe funzionato qualcosa come segue:

  • C'è una relazione separata tabella tra Individuals_v2 e Achievement (Individual_Achievement_v2 per ora, anche se deve esserci un nome migliore).

  • I dati nelle tabelle "v2" sono corretti, buoni e corretti. Le tabelle "v1" sono staging, cronologia, dati di registro.

  • Preparare una versione iniziale, dove tutte le voci nelle tabelle v1 sono configurate nelle tabelle v2. Se le righe possono essere consolidate durante questo passaggio, tanto meglio. Tutto viene registrato nella tabella "mappa", in modo che possano essere ripuliti e rifatti se necessario.

  • Andando avanti da questa versione, i nuovi dati vengono immessi nelle tabelle v1 e immessi contemporaneamente/immediatamente nelle tabelle v2. Se è possibile creare una mappatura a un articolo esistente, farlo, altrimenti creare una nuova voce nelle tabelle v2. Registra sempre l'attività nella tabella "mappa".

  • Andando avanti, tutte le query "Live" hanno colpito le tabelle v2. Le tabelle v1 sono (di nuovo) cronologia, registro, audit trail. Una volta popolati, non vengono mai modificati, mentre le tabelle v2 (compresa la tabella di mapping) possono essere e saranno.

  • Come determinato dall'azienda, vengono eseguite revisioni/verifiche periodiche sui dati, per cercare e correggere le voci duplicate che sono apparse nel tempo, nonché i "duplicati non validi" (mappature errate). Questo è quando si esegue il rollback/ripeti lavoro, come tracciato nelle tabelle di mappatura e v1.

avrete forse vogliono alcune tabelle di registrazione in più, per tenere traccia delle cose come “tutti i dati inseriti attraverso xx/xx/xxxx è valido, i dati inseriti da allora devono essere rivisti”. Sono sicuro che ci saranno altri problemi e sottigliezze che si presenteranno ... lo fanno sempre ...

+0

Vedo dove stai andando con quello, immagino che il più grande presupposto qui sia che un utente non creerà mai più un individuo duplicato. Se lo facessero, dovremmo ricominciare da capo con individual_v3. Per la tabella individual_assessment, dovresti aggiungere una colonna per individual_v2_id o semplicemente aggiornare la colonna individual_id? (E quindi creare un'altra tabella di mappatura anche per questo?) –

+0

Ha risposto a questo nella sezione "addenda" della risposta. –

+0

Grazie Phillip, questa è una soluzione molto più arrotondata. Pro: può eseguire il rollback di una singola unione singola anziché di un punto temporale (modello di comando). Contro: per ogni tabella che deve essere unita, sono necessarie 2 tabelle aggiuntive. –