您对我如何计算哪些是最密切相关的城市有疑问?例如。如果我查看城市 1(巴黎),结果应该是:伦敦 (2)、纽约 (3) 并且根据您提供的数据集,只有一件事可以关联,即城市之间的公共标签,因此共享公共标签的城市将是下面最接近的城市是查找共享公共标签的城市(除了提供查找其最近的城市)的子查询
SELECT * FROM `cities` WHERE id IN (
SELECT city_id FROM `cities_tags` WHERE tag_id IN (
SELECT tag_id FROM `cities_tags` WHERE city_id=1) AND city_id !=1 )
工作
我假设您将输入城市 id 或名称之一以找到最接近的城市 ID,在我的情况下,“Paris”的 ID 为 1
SELECT tag_id FROM `cities_tags` WHERE city_id=1
它会找到paris所有的标签id然后
SELECT city_id FROM `cities_tags` WHERE tag_id IN (
SELECT tag_id FROM `cities_tags` WHERE city_id=1) AND city_id !=1 )
它将获取除巴黎之外的所有城市,这些城市具有与巴黎相同的标签
这是你的Fiddle
在阅读 Jaccard 相似度/索引 时,发现一些东西可以理解这些术语的实际含义,让我们以这个例子为例,我们有两组 A 和 B
设置 A={A, B, C, D, E}
设置 B={I、H、G、F、E、D}
jaccard相似度计算公式为JS=(A intersect B)/(A
联合 B)
A 相交 B = {D,E}= 2
联合 B ={A, B, C, D, E,I, H, G, F} =9
JS=2/9 =0.2222222222222222
现在转向你的场景
Paris 的 tag_ids 为 1,3,所以我们制作了这个集合并调用我们的 Set
P ={欧洲,河流}
London 的 tag_ids 为 1,3,所以我们设置了这个并调用我们的
设置 L ={Europe,River}
纽约的 tag_ids 为 2,3,所以我们设置了这个并调用我们的
设置 NW ={北美,河流}
计算 JS Paris 和 London JSPL = P intersect L / P union L ,
JSPL = 2/2 = 1
计算 JS 巴黎和纽约 JSPNW = P intersect NW / P
联合 NW ,JSPNW = 1/3 = 0.3333333333
到目前为止,这是计算完美 jaccard 索引的查询,您可以看到下面的 fiddle 示例
SELECT a.*,
( (CASE WHEN a.`intersect` =0 THEN a.`union` ELSE a.`intersect` END ) /a.`union`) AS jaccard_index
FROM (
SELECT q.* ,(q.sets + q.parisset) AS `union` ,
(q.sets - q.parisset) AS `intersect`
FROM (
SELECT cities.`id`, cities.`name` , GROUP_CONCAT(tag_id SEPARATOR ',') sets ,
(SELECT GROUP_CONCAT(tag_id SEPARATOR ',') FROM `cities_tags` WHERE city_id= 1)AS parisset
FROM `cities_tags`
LEFT JOIN `cities` ON (cities_tags.`city_id` = cities.`id`)
GROUP BY city_id ) q
) a ORDER BY jaccard_index DESC
在上面的查询中,我已经将结果集派生为两个子选择,以便获得我的自定义计算别名
您可以在上面的查询中添加过滤器,而不是计算与自身的相似度
SELECT a.*,
( (CASE WHEN a.`intersect` =0 THEN a.`union` ELSE a.`intersect` END ) /a.`union`) AS jaccard_index
FROM (
SELECT q.* ,(q.sets + q.parisset) AS `union` ,
(q.sets - q.parisset) AS `intersect`
FROM (
SELECT cities.`id`, cities.`name` , GROUP_CONCAT(tag_id SEPARATOR ',') sets ,
(SELECT GROUP_CONCAT(tag_id SEPARATOR ',') FROM `cities_tags` WHERE city_id= 1)AS parisset
FROM `cities_tags`
LEFT JOIN `cities` ON (cities_tags.`city_id` = cities.`id`) WHERE cities.`id` !=1
GROUP BY city_id ) q
) a ORDER BY jaccard_index DESC
所以结果显示巴黎与伦敦密切相关,然后又与纽约相关
Jaccard Similarity Fiddle