我在 SQL 中有以下三个表:
select * from movie limit 2;
id | title | year | content_rating | duration | lang | country | gross | budget | director_id
------+----------------------------+------+----------------+----------+------------+----------------------+----------+----------+-------------
407 | 102 Dalmatians | 2000 | G | 100 | English | USA | 66941559 | 85000000 | 2174
3699 | 10 Cloverfield Lane | 2016 | PG-13 | 104 | English | USA | 71897215 | 15000000 | 1327
(2 rows)
select * from actor limit 3;
id | name | facebook_likes
------+----------------------+----------------
408 | Christian Bale | 23000
1430 | Donna Murphy | 553
66 | Robert Downey Jr. | 21000
(3 rows)
select * from acting limit 3;
movie_id | actor_id
----------+----------
407 | 2024
3699 | 1841
3016 | 11
(3 rows)
给定两个 Actor a1 和 a2,我想找到 a1 之间的最短 路径 和 a2。
例如,假设 a1 = 'Tom Cruise' 和 a2 = 'Robert Downey Jr'。
输出应该是
汤姆·克鲁斯和罗伯特·杜瓦尔一起出演了雷霆之日 -> 罗伯特·杜瓦尔和小罗伯特·唐尼一起出演了幸运儿
在这种情况下,汤姆·克鲁斯 与小罗伯特·唐尼 相差 2 度,罗伯特·杜瓦尔 连接着他们。最多,我想输出高达 10 度,然后忽略任何连接。
我尝试实现解决方案 SQL query 6 degrees of separation for network analysis使用递归 CTE,但我认为我没有正确应用它。感谢帮助,提前致谢:)
尝试查询:
with recursive cte as (
select actor.name, movie.title, 1 as level from movie
left join acting on acting.movie_id = movie.id
left join actor on actor.id = acting.actor_id
where actor.name = 'Tom Cruise'
union
select actor.name, movie.title, level+1 from movie
left join acting on acting.movie_id = movie.id
left join actor on actor.id = acting.actor_id
inner join cte on cte.name = actor.name
where cte.name = actor.name and cte.level < 10
)
select * from cte
最佳答案
我不确定您在查询中的第二个选择会返回什么,但这里有一种获取参与者之间分离度的方法:
假设我们有一张 Actor ID 表,Origin。为了获得与我们表中的其中一位 Actor 在同一部电影中扮演过的所有 Actor ,我们需要从 Origin 开始,加入 Acting 然后加入 Movie 以获得我们的原始 Actor 扮演过的所有电影,然后再次加入 Acting 和 Actor 表以获得我们想要的。请注意,代理表出现了两次。如果我们将此应用于递归 CTE 和您的问题,请注意 Origin 表在您的示例中将是 Cte,我们将得到以下结果:
WITH RECURSIVE cte(id, distance) AS (
SELECT actor.id, 0
FROM actor
WHERE actor.name = 'Tom Cruise'
UNION
SELECT DISTINCT actor.id, cte.distance + 1
FROM cte
JOIN acting AS acting1 ON (cte.id = acting1.actor_id)
JOIN movie ON (acting1.movie_id = movie.id)
JOIN acting AS acting2 ON (movie.id = acting2.movie_id)
JOIN actor ON (acting2.actor_id = actor.id)
WHERE cte.id <> actor.id AND cte.distance + 1 <= 10
)
在此之后,cte 表将包含类型为 (id, dist) 的元组,这意味着存在从汤姆克鲁斯到具有此 ID 且距离为 dist 的 Actor 的路径。
DISTINCT 是出于效率原因。我们的 Cte 表中会有很多错误对(第二个值大于真实距离),特别是如果 Actor 图是密集的,但正确的元组将在 Cte 表中.我所说的正确元组是指一个元组( Actor ,距离),这样的距离是起始 Actor (例如汤姆克鲁斯)和该 Actor 之间的最短路径。
编辑:糟糕,UNION 已经这样做了,所以重复不需要 DISTINCT。
为了获得该距离,我们添加了一个带有 group by 子句的选择:
WITH RECURSIVE cte(id, distance) AS (
SELECT actor.id, 0
FROM actor
WHERE actor.name = 'Tom Cruise'
UNION
SELECT actor.id, cte.distance + 1
FROM cte
JOIN acting AS acting1 ON (cte.id = acting1.actor_id)
JOIN movie ON (acting1.movie_id = movie.id)
JOIN acting AS acting2 ON (movie.id = acting2.movie_id)
JOIN actor ON (acting2.actor_id = actor.id)
WHERE cte.id <> actor.id AND cte.distance + 1 <= 10
)
SELECT id, MIN(distance) AS distance
FROM cte
GROUP BY id
ORDER BY 2 ASC;
如果您想查看给定的第二个 Actor 的结果,比如小罗伯特唐尼,那么这将为您提供有关分离度的答案:
WITH RECURSIVE cte(id, distance) AS (
SELECT actor.id, 0
FROM actor
WHERE actor.name = 'Tom Cruise'
UNION
SELECT actor.id, cte.distance + 1
FROM cte
JOIN acting AS acting1 ON (cte.id = acting1.actor_id)
JOIN movie ON (acting1.movie_id = movie.id)
JOIN acting AS acting2 ON (movie.id = acting2.movie_id)
JOIN actor ON (acting2.actor_id = actor.id)
WHERE cte.id <> actor.id AND cte.distance + 1 <= 10
), distance_table (id, distance) AS (
SELECT id, MIN(distance) AS distance
FROM cte
GROUP BY id
)
SELECT 'Tom Cruise and ' || actor.name || ' are separated by ' ||
COALESCE(TO_CHAR(distance_table.distance, '999999'), 'more than 10') || ' degrees of separation'
FROM actor
LEFT JOIN distance_table ON (actor.id = distance_table.id)
WHERE actor.name = 'Robert Downey Jr';
虽然我认为您一般不会想直接从数据库中计算此类信息,但如果您想要一条消息告诉 Actor 之间的路径,就像您提供的那样(汤姆克鲁斯在 Days雷霆与罗伯特·杜瓦尔 -> 罗伯特·杜瓦尔与小罗伯特·唐尼在《幸运的你》中),然后像这样的东西可以返回:
WITH RECURSIVE cte(id, name, distance, message) AS (
SELECT actor.id, actor.name, 0, ''
FROM actor
WHERE actor.name = 'Tom Cruise'
UNION
SELECT actor.id, actor.name, cte.distance + 1,
cte.message || '> ' || cte.name || ' was in ' ||
movie.title || ' with ' || actor.name || ' '
FROM cte
JOIN acting AS acting1 ON (cte.id = acting1.actor_id)
JOIN movie ON (acting1.movie_id = movie.id)
JOIN acting AS acting2 ON (movie.id = acting2.movie_id)
JOIN actor ON (acting2.actor_id = actor.id)
WHERE cte.id <> actor.id AND cte.distance + 1 <= 10
), distance_table (id, distance) AS (
SELECT id, MIN(distance) AS distance
FROM cte
GROUP BY id
)
SELECT id, name, message, distance
FROM cte
WHERE (id, distance) IN (SELECT * FROM distance_table)
ORDER BY distance;
关于php - 寻找最短路径最多分离十度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55717636/
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
如何使此根路径转到:“/dashboard”而不仅仅是http://example.com?root:to=>'dashboard#index',:constraints=>lambda{|req|!req.session[:user_id].blank?} 最佳答案 您可以通过以下方式实现:root:to=>redirect('/dashboard')match'/dashboard',:to=>"dashboard#index",:constraints=>lambda{|req|!req.session[:user_id].b
我需要根据字符串路径的长度将字符串路径数组转换为符号、哈希和数组的数组给定以下数组:array=["info","services","about/company","about/history/part1","about/history/part2"]我想生成以下输出,对不同级别进行分组,根据级别的结构混合使用符号和对象。产生以下输出:[:info,:services,about:[:company,history:[:part1,:part2]]]#altsyntax[:info,:services,{:about=>[:company,{:history=>[:part1,:pa
给定一个数组a,什么是实现其组合直到第n的最佳方法?例如:a=%i[abc]n=2#Expected=>[[],[:a],[:b],[:c],[:a,b],[:b,:c],[:c,:a]] 最佳答案 做如下:a=%w[abc]n=30.upto(n).flat_map{|i|a.combination(i).to_a}#=>[[],["a"],["b"],["c"],["a","b"],#["a","c"],["b","c"],["a","b","c"]] 关于ruby-最多n的组合,我
Organization和Image具有一对一的关系。Image有一个名为filename的列,它存储文件的路径。我在Assets管道中包含这样一个文件:app/assets/other/image.jpg。播种时如何包含此文件的路径?我已经在我的种子文件中尝试过:@organization=...@organization.image.create!(filename:File.open('app/assets/other/image.jpg'))#Ialsotried:#@organization.image.create!(filename:'app/assets/other/i
我安装了ruby、yeoman,当我运行我的项目时,出现了这个错误:Warning:Running"compass:dist"(compass)taskWarning:YouneedtohaveRubyandCompassinstalledthistasktowork.Moreinfo:https://github.com/gruUse--forcetocontinue.Use--forcetocontinue.我有进入可变session目标的路径,但它不起作用。谁能帮帮我? 最佳答案 我必须运行这个:geminstallcom
我有以下数组:arr=[1,3,2,5,2,4,2,2,4,4,2,2,4,2,1,5]我想要一个包含前三个奇数元素的数组。我知道我可以做到:arr.select(&:odd?).take(3)但我想避免遍历整个数组,而是在找到第三个匹配项后返回。我想出了以下解决方案,我相信它可以满足我的要求:my_arr.each_with_object([])do|el,memo|memo但是有没有更简单/惯用的方法来做到这一点? 最佳答案 使用lazyenumerator与Enumerable#lazy:arr.lazy.select(&:o
是否有内置的Ruby方法或众所周知的库可以返回对象的整个方法查找链?Ruby查看一系列令人困惑的类(如thisquestion中所讨论)以查找与消息对应的实例方法,如果没有类响应消息,则调用接收方的method_missing。我将以下代码放在一起,但我确信它遗漏了某些情况或者它是否100%正确。请指出任何缺陷并指导我找到一些更好的代码(如果存在)。defmethod_lookup_chain(obj,result=[obj.singleton_class])ifobj.instance_of?Classreturnadd_modules(result)ifresult.last==B
我正在寻找这样解析路由路径的方法:ActionController::Routing.new("post_path").parse#=>{:controller=>"posts",:action=>"index"}应该和url_for相反更新我发现:Whatistheoppositeofurl_forinRails?Afunctionthattakesapathandgeneratestheinterpretedroute?ActionController::Routing::Routes.recognize_path("/posts")所以现在我需要将posts_path转换为“/p