Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

A normalização dificulta as junções em várias tabelas


Não vou falar de erros ortográficos. Como você está importando os dados, os erros de ortografia são mais bem tratados em uma tabela de preparo.

Vejamos esta versão ligeiramente simplificada.
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');

Embora muitas pessoas acreditem firmemente que o CEP determina a cidade e o estado nos EUA, esse não é o caso. Os códigos postais têm a ver com a forma como as operadoras dirigem suas rotas, não com a geografia. Algumas cidades atravessam as fronteiras entre os estados; rotas de código postal único podem cruzar linhas de estado. Até a Wikipedia sabe disso , embora seus exemplos possam estar desatualizados. (As rotas de entrega mudam constantemente.)

Então temos uma tabela que tem duas chaves candidatas,
  • {store_name} e
  • {street_num, street_name, city, state_code, zip_code, iso_country_code}

Não possui atributos não-chave. Eu acho que esta tabela está em 5NF. O que você acha?

Se eu quisesse aumentar a integridade dos dados para nomes de ruas, poderia começar com algo assim.
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.

Você pode (e provavelmente deve) repetir esse processo para nomes de cidades, nomes de estados (códigos de estado) e nomes de países.

Alguns problemas com sua abordagem

Aparentemente, você pode inserir um número de identificação de rua para uma rua nos EUA, juntamente com a identificação do país para a Croácia. (O "nome completo" de uma cidade, por assim dizer, é o tipo de fato que você provavelmente deseja armazenar para aumentar a integridade dos dados. Isso provavelmente também vale para o "nome completo" de uma rua.)

O uso de números de identificação para cada bit de dados aumenta muito o número de junções necessárias. Usar números de identificação não tem nada a ver com normalização. O uso de números de identificação sem restrições exclusivas correspondentes nas chaves naturais - um erro totalmente comum - permite dados duplicados.