sql - 如何计算 SQL 数据库中两条线之间的距离?
问题描述
这是我的数据库示例,包含 3 个列:班级、年份和学生姓名。
我根据两个给定学生之间的普通学生搜索“距离”。(比如著名的游戏“6度培根”)
目标是计算 Momo Thary (2018) 和 Paul Biloux (2020) 之间的距离。答案是 2 个学生:Momo Thary 和 Jack Spiral 在同一个班。Jack Spiral 和 Lucien Lake 同班。Lucien Lake 和 Paul Biloux 同班。
所以我们可以将 Momo Thary 和 Paul Biloux 与 2 名学生“联系起来”。
我在网上使用 SQLite。通过以下代码,可以知道 Jack Spiral 和 Paul Biloux 的共同玩家:
WITH
names(name) AS (SELECT 'Jack Spiral' UNION ALL SELECT 'Paul Biloux'),
common AS (
SELECT class, year
FROM Lignes
WHERE student_name IN names
GROUP BY class, year
HAVING COUNT(DISTINCT student_name) = (SELECT COUNT(*) FROM names)
)
SELECT l1.student_name student
FROM Lignes l1 INNER JOIN Lignes l2
ON l2.year = l1.year AND l2.class = l1.class AND l2.student_name <> l1.student_name
WHERE l2.student_name IN names
GROUP BY student
HAVING COUNT(DISTINCT l2.student_name) = (SELECT COUNT(*) FROM names)
AND SUM((l1.class, l1.year) IN common) = 0
输出是吕西安湖。
但是如果我将这个脚本用于 Momo Thary 和 Paul Biloux,则没有输出。事实上,是不是需要先用 Jack Spiral 再用 Lucien Lake 来做链接。
是否可以调整脚本,首先知道最快的链接(如果有很多可能的链接),然后知道学生的路径是什么?SQL可能适合做这种类型的代码还是其他语言更合适?
解决方案
您可以使用递归查询:
WITH RECURSIVE rec(distance, student_name, path) AS (
-- start with Paul Biloux
SELECT 0, 'Paul Biloux', '|Paul Biloux|'
UNION
-- increment distance
SELECT r.distance + 1, l1.student_name, r.path || l1.student_name || '|'
FROM rec r
JOIN lignes l1
-- avoid loops
ON r.path NOT LIKE '%|' || l1.student_name || '|%'
-- there is a common class
WHERE exists (SELECT * FROM lignes l2 WHERE l2.year = l1.year AND l2.grade = l1.grade AND l2.student_name = r.student_name )
)
-- keep only the shortest path
-- if there are more than one, choose one randomely
-- (this is specific to SQLite)
SELECT student_name, MIN(distance) AS dist, path
FROM rec
GROUP BY student_name
ORDER BY distance
结果是:
student_name dist path
Paul Biloux 0 |Paul Biloux|
Lucien Lake 1 |Paul Biloux|Lucien Lake|
Thome Defoe 1 |Paul Biloux|Thome Defoe|
Chane Way 2 |Paul Biloux|Lucien Lake|Chane Way|
Jack Spiral 2 |Paul Biloux|Lucien Lake|Jack Spiral|
Mathilde Seine 3 |Paul Biloux|Lucien Lake|Jack Spiral|Mathilde Seine|
Momo Thary 3 |Paul Biloux|Lucien Lake|Jack Spiral|Momo Thary|
这是非常低效的,因为探索了所有可能的路径。
推荐阅读
- ruby-on-rails - 在关联错误消息中隐藏/删除模型名称
- python - 无法分配“
":" 必须是一个 "" 实例 - javascript - Laravel Passport API 向未使用付费号码的用户发送 OTP
- html - 无法使用 :link 选择器更改链接的颜色
- javascript - 使用 React 的地图加载不正确传单
- reactjs - 返回内部功能组件中的显示值
- javascript - 如何在 Chrome 的全局媒体控件中使用 blob URL 作为图像源?
- php - 如何缓存和重用 GuzzleHttp\Psr7\Response 的副本以进行调试?
- android - 大规模崩溃 org.altbeacon.beacon.service.ScanJob -> java.lang.RuntimeException: android.os.DeadSystemException
- node.js - Mongodb 连接池与单例线程