Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Die Normalisierung erschwert Joins über mehrere Tabellen hinweg

Ich werde nicht zu Rechtschreibfehlern sprechen. Da Sie die Daten importieren, werden Rechtschreibfehler besser in einer Staging-Tabelle behandelt.

Schauen wir uns diese leicht vereinfachte Version an.

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

Obwohl viele Leute fest davon überzeugt sind, dass die Postleitzahl in den USA Stadt und Staat bestimmt, ist das nicht der Fall. Postleitzahlen haben damit zu tun, wie Spediteure ihre Routen fahren, nicht mit der Geographie. Einige Städte überspannen die Grenzen zwischen Staaten; Einzelne Postleitzahlenrouten können Staatsgrenzen überqueren. Sogar Wikipedia weiß das , obwohl ihre Beispiele möglicherweise veraltet sind. (Lieferwege ändern sich ständig.)

Wir haben also eine Tabelle mit zwei Kandidatenschlüsseln,

  • {Geschäftsname} und
  • {street_num, street_name, city, state_code, zip_code, iso_country_code}

Es hat keine Nicht-Schlüsselattribute. Ich denke, diese Tabelle ist in 5NF. Was denkst du?

Wenn ich die Datenintegrität für Straßennamen erhöhen wollte, könnte ich mit so etwas anfangen.

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.

Sie könnten (und sollten wahrscheinlich) diesen Vorgang für Städtenamen, Bundesstaatsnamen (Staatscodes) und Ländernamen wiederholen.

Einige Probleme mit Ihrem Ansatz

Sie können anscheinend eine Straßen-ID-Nummer für eine Straße in den USA zusammen mit der Länder-ID für Kroatien eingeben. (Der "vollständige Name" einer Stadt ist sozusagen die Art von Tatsache, die Sie wahrscheinlich speichern möchten, um die Datenintegrität zu erhöhen. Das gilt wahrscheinlich auch für den "vollständigen Namen" einer Straße.)

Die Verwendung von ID-Nummern für jedes Datenbit erhöht die Anzahl der erforderlichen Verknüpfungen erheblich. Die Verwendung von ID-Nummern hat nichts mit Normalisierung zu tun. Die Verwendung von ID-Nummern ohne entsprechende Eindeutigkeitsbeschränkungen für die natürlichen Schlüssel – ein absolut häufiger Fehler – ermöglicht doppelte Daten.