邮件地址应该在SQL中规范化吗?

时间:2014-02-03 17:56:39

标签: php mysql sql database-design normalization

是否应将包含城市,州和邮政编码的邮寄地址规范化?我目前只关注美国地址。我已经显示了一个规范化的表格和一个ERD,以及这篇文章底部的非规范化表格。请为你的答案提供理性的答案。

请注意,To Normalize or Not To Normalize与此主题相关,但不同。

谢谢

enter image description here

CREATE  TABLE IF NOT EXISTS states (
  id CHAR(2) NOT NULL ,
  name VARCHAR(45) NULL DEFAULT NULL ,
  PRIMARY KEY (id) ,
  INDEX states_name (name ASC) )
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS cities (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  name VARCHAR(45) NOT NULL ,
  states_id CHAR(2) NOT NULL ,
  PRIMARY KEY (id) ,
  INDEX fk_zipcodes_states1_idx (states_id ASC) ,
  UNIQUE INDEX makeUnique (states_id ASC, name ASC) ,
  INDEX cities_name (name ASC) ,
  CONSTRAINT fk_zipcodes_states1
    FOREIGN KEY (states_id )
    REFERENCES states (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
PACK_KEYS = 0
ROW_FORMAT = DEFAULT;

CREATE  TABLE IF NOT EXISTS zipcode_types (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  name VARCHAR(45) NULL DEFAULT NULL ,
  PRIMARY KEY (id) )
ENGINE = InnoDB
PACK_KEYS = 0
ROW_FORMAT = DEFAULT;

CREATE  TABLE IF NOT EXISTS counties (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  name VARCHAR(45) NOT NULL ,
  PRIMARY KEY (id) ,
  INDEX counties_name (name ASC) )
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS timezones (
  id CHAR(4) NOT NULL ,
  name VARCHAR(45) NOT NULL ,
  PRIMARY KEY (id) )
ENGINE = InnoDB
PACK_KEYS = 0
ROW_FORMAT = DEFAULT;

CREATE  TABLE IF NOT EXISTS zipcodes (
  id CHAR(5) NOT NULL ,
  longitude DECIMAL(9,6) NOT NULL ,
  latitude DECIMAL(9,6) NOT NULL ,
  zipcode_types_id INT UNSIGNED NOT NULL ,
  counties_id INT UNSIGNED NOT NULL ,
  timezones_id CHAR(4) NOT NULL ,
  PRIMARY KEY (id) ,
  INDEX fk_zipcodes_zipcode_types1_idx (zipcode_types_id ASC) ,
  INDEX fk_zipcodes_counties1_idx (counties_id ASC) ,
  INDEX fk_zipcodes_timezones1_idx (timezones_id ASC) ,
  CONSTRAINT fk_zipcodes_zipcode_types1
    FOREIGN KEY (zipcode_types_id )
    REFERENCES zipcode_types (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT fk_zipcodes_counties1
    FOREIGN KEY (counties_id )
    REFERENCES counties (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT fk_zipcodes_timezones1
    FOREIGN KEY (timezones_id )
    REFERENCES timezones (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS cities_has_zipcodes (
  cities_id INT UNSIGNED NOT NULL ,
  zipcodes_id CHAR(5) NOT NULL ,
  PRIMARY KEY (cities_id, zipcodes_id) ,
  INDEX fk_cities_has_zipcodes_zipcodes1_idx (zipcodes_id ASC) ,
  INDEX fk_cities_has_zipcodes_cities1_idx (cities_id ASC) ,
  CONSTRAINT fk_cities_has_zipcodes_cities1
    FOREIGN KEY (cities_id )
    REFERENCES cities (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT fk_cities_has_zipcodes_zipcodes1
    FOREIGN KEY (zipcodes_id )
    REFERENCES zipcodes (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS someRecord (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  data VARCHAR(45) NULL ,
  address VARCHAR(45) NULL ,
  cities_id INT UNSIGNED NOT NULL ,
  zipcodes_id CHAR(5) NOT NULL ,
  PRIMARY KEY (id) ,
  INDEX fk_someRecord_cities1_idx (cities_id ASC) ,
  INDEX fk_someRecord_zipcodes1_idx (zipcodes_id ASC) ,
  CONSTRAINT fk_someRecord_cities1
    FOREIGN KEY (cities_id )
    REFERENCES cities (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT fk_someRecord_zipcodes1
    FOREIGN KEY (zipcodes_id )
    REFERENCES zipcodes (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

单个表中的数据示例

CREATE  TABLE IF NOT EXISTS otherRecord (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  data VARCHAR(45) NULL ,
  address VARCHAR(45) NULL ,
  city VARCHAR(45) NULL ,
  state VARCHAR(45) NULL ,
  zipcode VARCHAR(45) NULL ,
  county VARCHAR(45) NULL ,
  longitude DECIMAL(9,6) NULL ,
  latitude DECIMAL(9,6) NULL ,
  timezone VARCHAR(45) NULL ,
  PRIMARY KEY (id) )
ENGINE = InnoDB;

2 个答案:

答案 0 :(得分:1)

是的,如果:

  1. 您将分析您的数据的地址,我的意思是根据地址的各个字段对数据进行排序,过滤,分组和计数。

    如果您允许自由文字,那么您可能拥有美国,美国,美国,美国等国家/地区名称。如果您想查看/统计/分组所有美国客户,这将是一个痛苦。您的内部用户可能希望从大陆深入到国家/地区,从州到县,在这种情况下,您的数据需要进行规范化。

  2. 您将对外部来源进行匹配。例如,您拥有来自第三方供应商的数据,并且您需要匹配其公司A和您的公司A.通常,公司具有相似的名称,您需要匹配地址的(部分)。例如,您需要将“Acme,Inc | California”与“Acme Incorporated | CA”匹配。

  3. 您希望真正避免重复。如果您允许自由文本,那么您将获得“123-456 Main Street,Vancouver”和“Apt 123,456 Main Street,Vancouver”的副本

  4. 您想要真正有效数据。如果您允许自由文本,那么任何人都可以输入任何内容。这个很难,因为你需要大量的参考数据,包括可用的国家名称,州名,县名,甚至是街道名称。您可以从geonames.org获取一些数据。

  5. 请注意,爱尔兰不使用邮政编码,因此如果走向全球,您的架构需要考虑到这一点。阅读Hay的企业模型模式,了解一些优秀的地址模型。

答案 1 :(得分:0)

地址不是一个干净的关系实体。你不应该在传统意义上将它们标准化。您可能想要做的是另外存储地址部分的标准化版本(例如国家,州,城市),以用于您自己的分析目的,这是从用户提供的地址。

美国地址中存在大量例外情况,与世界其他地区相比,这些情况相当规范。顺便说一句,邮政编码主要与USPS的交付路线相对应,而不是与特定的物理位置相对应。

作为一个个人的例子,我居住在一个非法人区域,该区域由位于不同县(不同)的另一个(附近)城市的邮局提供服务。根据USPS,我的官方地址应写成“VC Highlands,NV 89521”,并且位于内华达州的Storey County。但是,邮政编码89521主要位于“Reno,NV 89521”,位于内华达州的Washoe县。你可以想象,这对每个人来说都是很麻烦的。甚至内华达州的DMV也拒绝接受“VC Highlands”,因为他们的数据库认为89521是“Reno”。

所以即使只是在上面的架构中使用“简单”的东西,你也错了。邮政编码不仅可以跨越多个城市,还可以跨越多个县。还有数以千计的例外情况肯定会让一部分用户感到沮丧。