Domanda

Ho una tabella con la seguente struttura:

WorkerPersons
-------------------------------
ID          (PK)
PersonID    (Indicates which version of Person the record describes)
SomeColumn1 (data specific to Worker)
SomeColumn2 (data specific to Person)
....
SomeColumnN
-------------------------------

Come puoi vedere, è una tabella denormalizzata, che contiene i dati di lavoratore e persona (e molte versioni di una persona) in una tabella. Il mio desiderio è di normalizzare quella tabella, tuttavia, poiché la tabella contiene molti dati (molte molte colonne), devo essere sicuro di quali colonne dovrebbero andare alla tabella dei lavoratori e quali colonne alla tabella delle persone. Il risultato dovrebbe essere così:

Workers                 Persons
----------------------- ---------------------
ID                      ID
PersonID (now a FK)     PersonColumn1
WorkerColumn1           PersonColumn2
WorkerColumn2           ...
...                     PersonColumnN
WorkerColumnN
----------------------- ---------------------

Per fare ciò, devo analizzare quali dati differiscono nell'ambito di persona su tutte le persone uniche (che sono separati da Personid in Workerpersons). Per esempio:

WorkerPersons
-------------------------------------------------------
ID      PersonID      Column1      Column2      Column3
-------------------------------------------------------
1       PersonA       10.1         John Doe     Single
2       PersonA       10.1         John Doe     Single
3       PersonA       10.1         John Doe     Married
4       PersonB       09.2         Sully        Single
5       PersonB       09.2         Sullivan     Single

In questo caso, ci sono 3 versioni su Persona e 2 versioni di PersonB. I valori di colonna1 sono sempre gli stessi su tutte le versioni della persona e possiamo spostare quella colonna al lavoratore della tabella. Ma i valori della colonna 2 e della colonna3 cambiano su diverse versioni della persona, quindi tali valori devono essere spostati nella tabella della persona.

Non immagina, ho circa 10 tabelle come questa che devono essere normalizzate, con circa 40 colonne in ciascuna. La tabella EEACH contiene circa 500k a 5 m di righe.

Ho bisogno di uno script che mi aiuti ad analizzare quali colonne si muovono dove. Ho bisogno di uno script che emette tutte le colonne che cambiano nell'ambito di una persona unica su tutta la tabella. Non ho idee, tuttavia come farlo. Ho sperimentato la funzione analitica LAG per confrontare la riga successiva, ma come nel mondo l'output cambiato colonne è al di là di me.

Si prega di avvisare.

I migliori auguri, Andrew

È stato utile?

Soluzione

Poiché 10 tabelle non sono molto, ecco (una sorta di) codice pseudo

for each table_name in tables
  for each column_name in columns
    case (exists (select 1
          from table_name
          group by PersonID
          having min(column_name) = max(column_name))
       when true then 'Worker'
       when false then 'Person'
    end case
  end for
end for

Con lo schema di informazione e le query dinamiche è possibile effettuare il PL/SQL corretto sopra o prendere la query di base e script nella tua lingua preferita.

MODIFICARE:Quanto sopra presuppone no NULLs in column_name.

EDIT2:Altre varianti della query di base possono essere

SELECT 1
FROM 
(SELECT COUNT(DISTINCT column_name) AS distinct_values_by_pid
FROM table_name
GROUP BY PersonID) T
HAVING MIN(distinct_values_by_pid) = MAX(distinct_values_by_pid)

Che restituirà una riga se tutti i valori per personale sono uguali. (Questa query ha anche problemi con i null, ma considero nulls un problema separato; puoi sempre lanciare un valore nullo su un valore fuori dominio ai fini della query sopra)

La query sopra può essere scritta anche come

SELECT MIN(c1)=MAX(c1), MIN(c2)=MAX(c2), ...
FROM 
(SELECT COUNT(DISTINCT column_name_1) AS c1, COUNT(DISTINCT column_name_2) AS c2, ...
FROM table_name
GROUP BY PersonID) T

Che testerà più colonne allo stesso tempo restituendo true per colonne che appartengono a "lavoratori" e falsi per colonne che dovrebbero andare in "persone".

Altri suggerimenti

Grazie, ma l'ho risolto lasciando che Excel crei serie di informazioni selezionate sullo schema della tabella. La query finale che ha generato è stata una lunga lista di selezioni ma funziona (anche se è durato per un'ora). La "query core" (in realtà una formula in Excel da creare per core query):

=IF(AND(C17<>"CLOB";C17<>"NCLOB");"SELECT '"&A17&".'||initcap('"&B17&"') description,
decode(count(*),0,'SAME OVE VERSIONS','DIFFERENT OVER VERSIONS') values FROM (SELECT 
objektid, count(DISTINCT nvl("&B17&","&IF(C17="DATE";"'01.02.0004'";IF(C17="VARCHAR2"
;"'!#¤¤%¤(%#¤%AS'";"-1234561"))&")) OVER (PARTITION BY objectid) arv FROM "&A17&") 
WHERE number > 1 union all";"SELECT '"&A17&".'||initcap('"&B17&"') description, 'CLOB
field' values from dual union all")
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top