题
我收到了一张大约有 18000 行的表。每条记录描述了一位客户的位置。问题是,当该人创建表时,他们没有添加“公司名称”字段,只添加“位置名称”字段,并且一个公司可以有多个位置。
例如,以下是描述同一客户的一些记录:
位置表
ID Location_Name
1 TownShop#1
2 Town Shop - Loc 2
3 The Town Shop
4 TTS - Someplace
5 Town Shop,the 3
6 Toen Shop4
我的目标是让它看起来像:
位置表
ID Company_ID Location_Name
1 1 Town Shop#1
2 1 Town Shop - Loc 2
3 1 The Town Shop
4 1 TTS - Someplace
5 1 Town Shop,the 3
6 1 Toen Shop4
公司表
Company_ID Company_Name
1 The Town Shop
没有“公司”表,我必须从代表多个位置的最具描述性或最佳位置名称生成公司名称列表。
目前我想我需要生成一个相似的位置名称列表,然后手动浏览该列表。
任何有关我如何解决此问题的建议都将受到赞赏。
@Neall,谢谢您的陈述,但不幸的是,每个位置名称都是不同的,没有重复的位置名称,只有相似。因此,在语句的结果中,每行“repcount”为 1。
@yukondude,你的第 4 步是我问题的核心。
解决方案
请更新问题,您有可用的公司名称列表吗?我问这个问题是因为您也许可以使用 Levenshtein 算法来查找 CompanyNames 和 LocationNames 列表之间的关系。
更新
没有公司名称列表,我必须从代表多个位置的最具描述性或最佳位置名称生成公司名称。
好的...尝试这个:
- 通过查找大部分或全部由字母字符组成的位置名称来构建候选公司名称列表。您可以使用 常用表达 为了这。将此列表存储在单独的表中。
- 按字母顺序对该列表进行排序,并(手动)确定哪些条目应该是公司名称。
- 将每个 CompanyName 与每个 LocationName 进行比较并得出匹配分数(使用 编辑 或其他一些字符串匹配算法)。将结果存储在单独的表中。
- 设置阈值分数,使得任何 MatchScore < 阈值都不会被视为与给定 CompanyName 的匹配。
- 通过CompanyName手动浏览位置名称|位置名称| MatchScore,并找出哪些实际匹配。按 MatchScore 排序应该可以减轻这个过程的痛苦。
上述操作的全部目的是使零件自动化并限制问题的范围。它远非完美,但有望帮助您省去手动查看 18K 记录的麻烦。
其他提示
我以前也不得不这么做过。唯一真正的方法是手动匹配各个位置。使用数据库的控制台界面和分组选择语句。首先,添加您的“公司名称”字段。然后:
SELECT count(*) AS repcount, "Location Name" FROM mytable
WHERE "Company Name" IS NULL
GROUP BY "Location Name"
ORDER BY repcount DESC
LIMIT 5;
找出列表顶部的位置属于哪家公司,然后使用 UPDATE ... 更新您的公司名称字段WHERE“位置名称”=“位置”语句。
附:- 您确实应该将公司名称和位置名称分成单独的表,并通过主键引用它们。
更新:- 哇 - 没有重复项?你有多少记录?
我本来打算推荐一些复杂的标记匹配算法,但要正确使用它确实很棘手,并且如果您的数据没有很多相关性(拼写错误等),那么它不会给出很好的结果。
我建议您向以下机构提交一份工作 亚马逊土耳其机器人 并让人来解决它。
理想情况下,您可能需要一个名为 Company 的单独表,然后在此“Location”表中添加一个 company_id 列,该列是 Company 表主键的外键(可能称为 id)。这将避免该表中出现相当多的文本重复(超过 18,000 行,整数外键将在 varchar 列上节省大量空间)。
但是您仍然面临着一种加载 Company 表,然后将其与 Location 中的行正确关联的方法。没有通用的解决方案,但您可以按照以下方式做一些事情:
- 创建 Company 表,其中包含自动递增的 id 列(取决于您的 RDBMS)。
- 找到所有唯一的公司名称并将它们插入到 Company 中。
- 将列 company_id 添加到接受 NULL 的位置(目前),并且该列是 Company.id 列的外键。
- 对于位置中的每一行,确定相应的公司,并使用该公司的 ID 更新该行的 company_id 列。这可能是最具挑战性的一步。如果您的数据如示例中所示,您可能需要使用各种字符串匹配方法进行多次运行。
- 一旦Location中的所有行都有company_id值,那么您可以更改Company表以将NOT NULL约束添加到company_id列(假设每个位置 必须 有一家公司,这似乎很合理)。
如果您可以复制 Location 表,则可以逐渐构建一系列 SQL 语句来填充 company_id 外键。如果您犯了错误,您可以重新开始并重新运行脚本直到失败为止。
是的,我上一篇文章中的第 4 步太棒了。
无论如何,您可能必须手动完成其中一些工作,但您也许能够将大部分工作自动化。对于您提供的示例位置,如下所示的查询将设置适当的 company_id 值:
UPDATE Location
SET Company_ID = 1
WHERE (LOWER(Location_Name) LIKE '%to_n shop%'
OR LOWER(Location_Name) LIKE '%tts%')
AND Company_ID IS NULL;
我相信这会匹配你的例子(我添加了 IS NULL
部分不覆盖以前设置的 Company_ID 值),但当然,在 18,000 行中,您必须非常有创意才能处理各种组合。
其他可能有用的方法是使用 Company 中的名称来生成类似于上面的查询。你可以执行如下操作(在 MySQL 中):
SELECT CONCAT('UPDATE Location SET Company_ID = ',
Company_ID, ' WHERE LOWER(Location_Name) LIKE ',
LOWER(REPLACE(Company_Name), ' ', '%'), ' AND Company_ID IS NULL;')
FROM Company;
然后只需运行它生成的语句即可。这可以为你做很多垃圾工作。