sql >> Database >  >> RDS >> Mysql

Normalisatie maakt joins over meerdere tabellen moeilijk

Ik ga niet praten over spelfouten. Aangezien u de gegevens importeert, kunnen spelfouten beter worden afgehandeld in een verzameltabel.

Laten we eens kijken naar deze enigszins vereenvoudigde versie.

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

Hoewel veel mensen er vast van overtuigd zijn dat postcode bepalend is voor stad en staat in de VS, is dat niet het geval. Postcodes hebben te maken met hoe vervoerders hun routes rijden, niet met geografie. Sommige steden overspannen de grenzen tussen staten; routes met enkele postcode kunnen staatsgrenzen overschrijden. Zelfs Wikipedia weet dit , hoewel hun voorbeelden misschien verouderd zijn. (Bezorgroutes veranderen voortdurend.)

We hebben dus een tabel met twee kandidaatsleutels,

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

Het heeft geen niet-essentiële kenmerken. Ik denk dat deze tafel in 5NF is. Wat denk je?

Als ik de gegevensintegriteit voor straatnamen zou willen vergroten, zou ik met zoiets als dit kunnen beginnen.

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.

U kunt (en moet waarschijnlijk) dit proces herhalen voor plaatsnamen, staatsnamen (staatcodes) en landnamen.

Enkele problemen met uw aanpak

U kunt blijkbaar een straat-ID-nummer invoeren voor een straat in de VS, samen met het land-ID voor Kroatië. (De "volledige naam" van een stad is bij wijze van spreken het soort feit dat u waarschijnlijk wilt opslaan om de gegevensintegriteit te vergroten. Dat geldt waarschijnlijk ook voor de "volledige naam" van een straat.)

Het gebruik van id-nummers voor elk stukje gegevens verhoogt het aantal benodigde joins aanzienlijk. Het gebruik van id-nummers heeft niets te maken met normalisatie. Het gebruik van id-nummers zonder bijbehorende unieke beperkingen op de natuurlijke sleutels - een volkomen alledaagse fout - maakt dubbele gegevens mogelijk.




  1. Hoe een resultaatset te krijgen zoals de Oracle-lagfunctie?

  2. Mysql-som van records per maand voor de afgelopen 12 maanden

  3. Heroku Postgresql met Google Datastudio

  4. SqlDataSourceEnumerator.Instance.GetDataSources() kan lokale SQL Server 2008-instantie niet vinden