验证从一个 table 到另一个 MySQL 中的字段

Validate fields from one table to another in MySQL

问题:

我有 1 table 大约 5000 行 称为 imported_cities

我有 1 table 大约 800 000 行 称为 postal_codes 包含邮政编码城市

我需要根据城市名称及其所在省份根据邮政编码table中的城市验证每个不同的城市。请参阅下面的 table 结构。

如果它们完全匹配(是的,完全匹配。其余城市是手动验证的)我必须更新imported_city上的一列 和 将imported_cities城市和postal_codes城市(并排)输入第三个table 称为 imported_cities_equiv

我试过的: 将索引添加到 tables 并在下面进行查询。 需要永远... :(

explain SELECT DISTINCT ic.destinationCity, pc.city FROM (imported_cities ic, postalcodes pc)
WHERE LOWER(ic.destinationCity) = LOWER(pc.city) 

结果

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ip index NULL  company_city 478 NULL 4221 Using index; Using temporary 
1 SIMPLE pc index NULL city_prov 160 NULL 765407 Using where; Using index; Using join buffer (Block...

--

-- Table table postalcodes

的结构
CREATE TABLE IF NOT EXISTS `postalcodes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(11) NOT NULL,
  `city` varchar(50) NOT NULL,
  `province` varchar(50) NOT NULL,
  `provinceISO` varchar(2) NOT NULL,
  `latitude` decimal(17,13) NOT NULL,
  `longitude` decimal(17,13) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `code` (`code`),
  KEY `city_prov` (`city`,`provinceISO`)

--

-- Table table imported_cities

的结构
CREATE TABLE IF NOT EXISTS `imported_cities` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `companyName` varchar(30) CHARACTER SET utf8 NOT NULL,
  `destinationCity` varchar(128) CHARACTER SET utf8 NOT NULL,
  `destinationProvince` varchar(20) CHARACTER SET utf8 NOT NULL,
  `equivCity` varchar(128) CHARACTER SET utf8 DEFAULT NULL,
  `minAmount` decimal(6,2) NOT NULL
  PRIMARY KEY (`id`),
  KEY `company_city` (`companyName`,`destinationCity`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci     AUTO_INCREMENT=7933 ;

--

-- Table table imported_cities_equiv

的结构
CREATE TABLE IF NOT EXISTS `imported_cities_equiv` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `imported_city` varchar(128) CHARACTER SET utf8 NOT NULL,
  `pc_city` varchar(128) CHARACTER SET utf8 NOT NULL,
  `province` varchar(20) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=149 ;

如有任何帮助或建议,我们将不胜感激。谢谢。

您要获取信息的查询是:

SELECT ip.*, (pc.city is not null) as exact match
FROM imported_prices ip left join
     postalcodes pc
     on LOWER(ip.destinationCity) = LOWER(pc.city)  and
        lower(ip.province) = lower(pc.province);

然而,这将有非常糟糕的表现。摆脱 lower() 会有所帮助:

SELECT ip.*, (pc.city is not null) as exact match
FROM imported_prices ip left join
     postalcodes pc
     on(ip.destinationCity) =(pc.city)  and
       (ip.province) = (pc.province);

因为这样您就可以在 postalcodes(city, province) 上添加索引。

如果您不能使用删除 lower(),则更改 table 以添加新列并将小写值放入这些列中。然后在新列上建立索引并在连接中使用它们。

谢谢大家给我指明了正确的方向。

根据您的建议进行了一些更改:

  • 在 destinationCity 和 destinationProvince 列的 imported_cities table 上添加了索引
  • 在城市和省份 ISO 列table 上添加了邮政编码索引
  • JOIN 子句只有一侧大写,因为字段 ic.destinationCity 已经是大写
  • 按省份限制 WHERE 性能查询

最后的SQL是:

SELECT DISTINCT pc.city, pc.provinceISO
FROM  postalcodes pc
    LEFT JOIN imported_cities ic
     ON upper(pc.city) = ic.destinationCity AND
     pc.provinceISO = ic.destinationProvince
     WHERE ic.destinationProvince = 'QC';

和解释

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  pc  ref province    province    8   const   278115  Using index condition; Using temporary
1   SIMPLE  ip  ref destinationCity,destinationProvince destinationCity 386 func    1   Using index condition; Using where; Distinct

展望未来,我现在可以在 PHP 上构建 INSERT 查询,并进行一个 INSERT 查询以在 3rd table 上插入所有等效城市。谢谢大家