Mysql
 sql >> Base de données >  >> RDS >> Mysql

La normalisation rend les jointures entre plusieurs tables difficiles

Je ne parlerai pas des fautes d'orthographe. Puisque vous importez les données, les fautes d'orthographe sont mieux gérées dans une table intermédiaire.

Regardons cette version légèrement simplifiée.

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');

Bien que beaucoup de gens croient fermement que le code postal détermine la ville et l'état aux États-Unis, ce n'est pas le cas. Les codes postaux ont à voir avec la façon dont les transporteurs conduisent leurs itinéraires, pas avec la géographie. Certaines villes chevauchent les frontières entre les États; les itinéraires à code postal unique peuvent traverser les lignes d'état. Même Wikipedia le sait , bien que leurs exemples puissent être obsolètes. (Les itinéraires de livraison changent constamment.)

Nous avons donc une table qui a deux clés candidates,

  • {store_name}, et
  • {street_num, street_name, city, state_code, zip_code, iso_country_code}

Il n'a pas d'attributs non clés. Je pense que ce tableau est en 5NF. Qu'en pensez-vous ?

Si je voulais augmenter l'intégrité des données pour les noms de rue, je pourrais commencer par quelque chose comme ça.

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.

Vous pouvez (et devriez probablement) répéter ce processus pour les noms de ville, les noms d'état (codes d'état) et les noms de pays.

Quelques problèmes avec votre approche

Vous pouvez apparemment entrer un numéro d'identification de rue pour une rue qui se trouve aux États-Unis, ainsi que l'identifiant du pays pour la Croatie. (Le "nom complet" d'une ville, pour ainsi dire, est le genre de fait que vous souhaitez probablement stocker afin d'augmenter l'intégrité des données. C'est probablement aussi vrai du "nom complet" d'une rue.)

L'utilisation de numéros d'identification pour chaque bit de données augmente considérablement le nombre de jointures requises. L'utilisation de numéros d'identification n'a rien à voir avec la normalisation. L'utilisation de numéros d'identification sans contraintes uniques correspondantes sur les clés naturelles (une erreur tout à fait courante) permet de dupliquer les données.