两个MySQL表之间的最长前缀

时间:2015-07-03 19:06:38

标签: php mysql symfony phone-number cdr

我有一个包含2个表的MySQL数据库:

表A:

  • 位置

表B:

  • 致电代码
  • 区号
  • 位置

最初,我在表A中有大约60,000个条目,其开头的Location列为空。在表B中,我有大约250,000多个条目,其中包含许多区号,呼叫代码(1,01)以及它们在世界上的相应位置。我想要的是一种快速的方法,用表格的位置填充表格A的位置列。

因此,例如,如果表A中的第一个条目是(17324765600,null),我想通过表B读取并获取该数字的位置。现在我正在使用此查询获取数字的位置:

SELECT b.location
FROM 
  tableB b
  LEFT JOIN tableA a
     ON a.number LIKE CONCAT(b.calling_code, b.code, '%')
ORDER BY CHAR_LENGTH(b.code) DESC
LIMIT 1;

这给了我正确的位置(即使我怀疑它可能会失败......)。问题是表现明智这种方法是不行的。如果我循环遍历所有50k数字

更新1

请允许我提供一些预期输出的样本数据: 样本表A:

number  location
17324765600 NULL
01134933638950  NULL
0114008203800   NULL
…60k Records + at the moment..

样本表B:

calling_code    code    location
1   7324765 US-NJ
011 34933   Spain
011 400820  China
…250,000+ records at the moment

处理后的预期输出: 表A:

number  location
17324765600 US-NJ
01134933638950  Spain
0114008203800   China

我提出的最好的是以下更新声明:

UPDATE tableA a JOIN tableB b ON a.location LIKE CONCAT(b.calling_code, b.code, '%') SET a.location = b.location

当然在这里我不确定它是否总会返回代码的最长前缀,例如,如果在上面的表格中有另一个以73247XX开头的代码,那么就说代码是针对爱荷华州的(仅作为示例)。我不确定查询是否总会返回最长的代码,所以在这里我也需要帮助。

如果样本有帮助,请告诉我。

.SQL用于数据库结构: Download

更新2:

我正在考虑以下方式:

在表AI中插入数据之前我想将表B导出为CSV并按区号对其进行排序,这样我可以有2个指针用于表A的条目数组和1个用于csv的指针,两个指针都已排序通过区域代码,我可以进行一种并行搜索并在PHP上填充条目的位置,而不必在MySQL中执行此操作。

让我知道这种方法是否是一个更好的选择,如果是这样我会测试它并发布答案。

3 个答案:

答案 0 :(得分:0)

如果您想要所有地点,则需要删除 LIMIT

SELECT b.location
FROM 
  tableB b
  LEFT JOIN tableA a
     ON a.number LIKE CONCAT(b.calling_code, b.code, '%')
ORDER BY CHAR_LENGTH(b.code);

如果您希望相同的位置名称不应该两次,那么您需要使用 GROUP BY

SELECT b.location
FROM 
  tableB b
  LEFT JOIN tableA a
     ON a.number LIKE CONCAT(b.calling_code, b.code, '%')
GROUP BY b.location  ORDER BY CHAR_LENGTH(b.code) ;

答案 1 :(得分:0)

你只有一个连接只有250000条记录,它没那么紧张。您应该对搜索列和fine tune your mysql server进行正确的索引编制。设置good indexing & server variables well可以轻松解决您的问题。优化您的查询。一般情况下,当我们有很多连接时会产生问题。许多字符串比较。

我认为您需要这样的查询 -

UPDATE a SET a.location = ( 
                            SELECT location from b 
                            WHERE a.number LIKE CONCAT(b.calling_code, b.area_code, '%') 
                            ORDER BY LENGTH(CONCAT(b.calling_code, b.area_code, '%')) desc 
                            limit 1
                          );

答案 2 :(得分:0)

我决定采取以下方法,因为我没有收到任何明确的答复:

在此过程之前,我准备了2个新表,一个国家代码表和一个州代码表(因为我还需要知道该号码在美国境内的状态)。两个表都有:country,state,calling_code,code ...

对于这两个表格,我用前缀分解了所有数字并按地区代码分组,所以我没有用完整的6个数字来识别国家/地区,而是按照前3个数字对它们进行分组,如果代码在美国与否,因此有两个表格。

通过这些修改,我能够将250,000 +行表分解为仅约300行(每个表)。

在此之后,我将遵循以下步骤:

  1. 我收到了电话号码列表
  2. 我首先执行的查询与我发布的查询非常相似,以更新属于country_code表的所有数字
  3. 然后我更新仍然没有使用state_code
  4. 表分配位置的行
  5. 为了避免拥有大量的手机,我必须放置某种cron以便每隔x段完成一次这样的操作。
  6. 这可能不是最好的方法,但对于我能够(通过查询手动执行查询以及更多抛光)的50k数字,将其降低到大约10秒,每x个执行一次时间(这将允许执行此过程少于1万个数字)将顺利完成。

    我会将此标记为答案,但如果有其他人神奇地想出更好的答案,我会确保更新。

    分而治之!