Mysql
 sql >> Database >  >> RDS >> Mysql

La normalizzazione rende difficili i join su più tabelle

Non parlerò di errori di ortografia. Poiché stai importando i dati, gli errori di ortografia vengono gestiti meglio in una tabella di staging.

Diamo un'occhiata a questa versione leggermente semplificata.

create table stores
(
  store_name varchar(50) primary key,
  street_num varchar(10) not null,
  street_name varchar(50) not null,
  city varchar(50) not null,
  state_code char(2) not null,
  zip_code char(5) not null,
  iso_country_code char(2) not null,
  -- Depending on what kind of store you're talking about, you *could* have
  -- two of them at the same address. If so, drop this constraint.
  unique (street_num, street_name, city, state_code, zip_code, iso_country_code)
);  

insert into stores values 
('Dairy Queen #212',  '232', 'N 1st St SE',   'Castroville',  'CA', '95012', 'US'),
('Dairy Queen #213',  '177', 'Broadway Ave',  'Hartsdale',    'NY', '10530', 'US'),
('Dairy Queen #214', '7640', 'Vermillion St', 'Seneca Falls', 'NY', '13148', 'US'),
('Dairy Queen #215', '1014', 'Handy Rd',      'Olive Hill',   'KY', '41164', 'US'),
('Dairy Mart #101',   '145', 'N 1st St SE',   'Castroville',  'CA', '95012', 'US'),
('Dairy Mart #121',  '1042', 'Handy Rd',      'Olive Hill',   'KY', '41164', 'US');

Sebbene molte persone credano fermamente che il codice postale determini la città e lo stato negli Stati Uniti, non è così. I codici postali hanno a che fare con il modo in cui i vettori guidano le loro rotte, non con la geografia. Alcune città si trovano a cavallo dei confini tra gli stati; i percorsi con codice postale singolo possono attraversare i confini di stato. Anche Wikipedia lo sa , anche se i loro esempi potrebbero non essere aggiornati. (I percorsi di consegna cambiano costantemente.)

Quindi abbiamo una tabella che ha due chiavi candidate,

  • {store_name} e
  • {numero_via, nome_via, città, codice_stato, codice_postale, codice_iso_paese}

Non ha attributi non chiave. Penso che questa tabella sia in 5NF. Cosa ne pensi?

Se volessi aumentare l'integrità dei dati per i nomi delle strade, potrei iniziare con qualcosa del genere.

create table street_names
(
  street_name varchar(50) not null,
  city varchar(50) not null,
  state_code char(2) not null,
  iso_country_code char(2) not null,
  primary key (street_name, city, state_code, iso_country_code)
);  

insert into street_names
select distinct street_name, city, state_code, iso_country_code
from stores;

alter table stores
add constraint streets_from_street_names
foreign key             (street_name, city, state_code, iso_country_code)
references street_names (street_name, city, state_code, iso_country_code);
-- I don't cascade updates or deletes, because in my experience
-- with addresses, that's almost never the right thing to do when a 
-- street name changes.

Potresti (e probabilmente dovresti) ripetere questo processo per nomi di città, nomi di stato (codici di stato) e nomi di paese.

Alcuni problemi con il tuo approccio

Apparentemente puoi inserire un numero di identificazione stradale per una strada che si trova negli Stati Uniti, insieme all'ID del paese per la Croazia. (Il "nome completo" di una città, per così dire, è il tipo di fatto che probabilmente vorrai memorizzare per aumentare l'integrità dei dati. Questo è probabilmente vero anche per il "nome completo" di una strada.)

L'utilizzo di numeri ID per ogni bit di dati aumenta notevolmente il numero di join richiesti. L'uso dei numeri ID non ha nulla a che fare con la normalizzazione. L'utilizzo di numeri ID senza corrispondenti vincoli univoci sulle chiavi naturali, un errore assolutamente comune, consente la duplicazione dei dati.