q20.sql 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. \set company '\'Balkh_Airlines\''
  2. \set person2Id 10995116285979::bigint
  3. -- CREATE MATERIALIZED VIEW
  4. -- Time: 650.821 ms
  5. -- CREATE INDEX
  6. -- Time: 476.647 ms
  7. -- t | w
  8. -- ---+---
  9. -- (0 rows)
  10. --
  11. -- Time: 843.523 ms
  12. -- emptiness is expected from a 20a parameter!
  13. \set company '\'National_Airlines_(5M)\''
  14. \set person2Id 13194139540317::bigint
  15. -- CREATE MATERIALIZED VIEW
  16. -- Time: 469.903 ms
  17. -- CREATE INDEX
  18. -- Time: 568.686 ms
  19. -- dst | w
  20. -- ----------------+---
  21. -- 24189255819104 | 3
  22. -- (1 row)
  23. --
  24. -- Time: 99518.999 ms (01:39.519)
  25. -- Time: 0.145 ms
  26. /* Q20. Recruitment
  27. \set person2Id 32985348834889
  28. \set company 'Express_Air'
  29. */
  30. -- edge relation
  31. CREATE OR REPLACE VIEW PathQ20 AS
  32. SELECT p1.personid AS src, p2.personid AS dst, min(abs(p1.classYear - p2.classYear)) + 1 AS w
  33. FROM Person_knows_person pp, Person_studyAt_University p1, Person_studyAt_University p2
  34. WHERE pp.person1id = p1.personid
  35. AND pp.person2id = p2.personid
  36. AND p1.universityid = p2.universityid
  37. GROUP BY p1.personid, p2.personid;
  38. CREATE INDEX PathQ20_src ON PathQ20 (src);
  39. -- materialize=> select count(*) from PathQ20;
  40. -- count
  41. -- -------
  42. -- 13732
  43. -- (1 row)
  44. --
  45. -- Time: 22.068 ms
  46. \set limit 1000
  47. WITH minimal_paths AS (
  48. WITH MUTUALLY RECURSIVE
  49. paths (src bigint, dst bigint, w bigint) AS (
  50. SELECT :person2Id AS src, :person2Id AS dst, 0 AS w
  51. UNION
  52. SELECT paths1.src, paths2.dst, paths1.w + paths2.w
  53. FROM minimal_paths paths1
  54. JOIN PathQ20 paths2 -- step-transitive closure
  55. ON paths1.dst = paths2.src
  56. ),
  57. minimal_paths (src bigint, dst bigint, w bigint) AS (
  58. SELECT src, dst, min(w)
  59. FROM paths
  60. GROUP BY src, dst
  61. )
  62. SELECT src, dst, w FROM minimal_paths),
  63. dsts AS (
  64. SELECT personid
  65. FROM Person_workat_company pwc, Company c
  66. WHERE pwc.companyid = c.id AND c.name=:company
  67. ),
  68. completed_paths AS (
  69. SELECT dst, w
  70. FROM minimal_paths
  71. WHERE dst IN (SELECT * FROM dsts)
  72. ),
  73. results AS (
  74. SELECT dst, w
  75. FROM completed_paths
  76. WHERE w IN (SELECT min(w) FROM completed_paths)
  77. )
  78. SELECT dst, w FROM results ORDER BY dst LIMIT 20;
  79. -- dropping the unused src
  80. /*
  81. WITH minimal_paths AS (
  82. WITH MUTUALLY RECURSIVE
  83. paths (dst bigint, w bigint) AS (
  84. SELECT :person2Id AS dst, 0 AS w
  85. UNION
  86. SELECT paths2.dst, paths1.w + paths2.w
  87. FROM minimal_paths paths1
  88. JOIN PathQ20 paths2 -- step-transitive closure
  89. ON paths1.dst = paths2.src
  90. ),
  91. minimal_paths (dst bigint, w bigint) AS (
  92. SELECT dst, min(w)
  93. FROM paths
  94. GROUP BY dst
  95. )
  96. SELECT dst, w FROM minimal_paths),
  97. dsts AS (
  98. SELECT personid
  99. FROM Person_workat_company pwc, Company c
  100. WHERE pwc.companyid = c.id AND c.name=:company
  101. ),
  102. completed_paths AS (
  103. SELECT dst, w
  104. FROM minimal_paths
  105. WHERE dst IN (SELECT * FROM dsts)
  106. ),
  107. results AS (
  108. SELECT dst, w
  109. FROM completed_paths
  110. WHERE w IN (SELECT min(w) FROM completed_paths)
  111. )
  112. SELECT dst, w FROM results ORDER BY dst LIMIT 20;
  113. */
  114. -- tracking hops
  115. /*
  116. WITH minimal_paths AS (
  117. WITH MUTUALLY RECURSIVE (RETURN AT RECURSION LIMIT=:limit)
  118. paths (src bigint, dst bigint, w bigint, hops bigint) AS (
  119. SELECT :person2Id AS src, :person2Id AS dst, 0 AS w, 0 AS hops
  120. UNION
  121. SELECT paths1.src, paths2.dst, paths1.w + paths2.w, paths1.hops + 1
  122. FROM minimal_paths paths1
  123. JOIN PathQ20 paths2 -- step-transitive closure
  124. ON paths1.dst = paths2.src
  125. ),
  126. minimal_weights (src bigint, dst bigint, w bigint, hops bigint) AS (
  127. SELECT src, dst, min(w), hops
  128. FROM paths
  129. GROUP BY src, dst, hops
  130. ),
  131. minimal_paths (src bigint, dst bigint, w bigint, hops bigint) AS (
  132. SELECT src, dst, w, min(hops)
  133. FROM minimal_weights
  134. GROUP BY src, dst, w
  135. )
  136. SELECT src, dst, w, hops FROM minimal_paths),
  137. dsts AS (
  138. SELECT personid
  139. FROM Person_workat_company pwc, Company c
  140. WHERE pwc.companyid = c.id AND c.name=:company
  141. ),
  142. completed_paths AS (
  143. SELECT dst, w, hops
  144. FROM minimal_paths
  145. WHERE dst IN (SELECT * FROM dsts)
  146. ),
  147. results AS (
  148. SELECT dst, w, hops
  149. FROM completed_paths
  150. WHERE w IN (SELECT min(w) FROM completed_paths)
  151. )
  152. SELECT dst, w, hops FROM results ORDER BY dst LIMIT 20;
  153. */
  154. /*
  155. WITH MUTUALLY RECURSIVE
  156. srcs(f bigint) AS (SELECT :person2Id),
  157. dsts(t bigint) AS (
  158. SELECT personid
  159. FROM Person_workat_company pwc, Company c
  160. WHERE pwc.companyid = c.id AND c.name=:company
  161. ),
  162. -- Try to find any path with a faster two way BFS
  163. -- visited nodes plus (on each iteration) nodes in PathQ20 we haven't yet seen
  164. anyPath (pos bigint) AS (
  165. SELECT f FROM srcs
  166. UNION
  167. (
  168. WITH
  169. ss AS (SELECT pos FROM anyPath)
  170. SELECT dst
  171. FROM ss, PathQ20
  172. WHERE pos = src AND NOT EXISTS (SELECT 1 FROM ss, dsts WHERE ss.pos = dsts.t)
  173. )
  174. ),
  175. -- are we there yet? at first, no (unless src is a dst)
  176. pathexists (exists bool) AS (
  177. SELECT true WHERE EXISTS (SELECT 1 FROM anyPath ss, dsts WHERE ss.pos = dsts.t)
  178. ),
  179. shorts (dir bool, gsrc bigint, dst bigint, w bigint, dead bool, iter bigint) AS (
  180. (
  181. SELECT false, f, f, 0, false, 0 FROM srcs WHERE EXISTS (SELECT 1 FROM pathexists)
  182. UNION
  183. SELECT true, t, t, 0, false, 0 FROM dsts WHERE EXISTS (SELECT 1 FROM pathexists)
  184. )
  185. UNION
  186. (
  187. WITH ss AS (SELECT * FROM shorts),
  188. toExplore AS (SELECT * FROM ss WHERE dead = false ORDER BY w limit 1000),
  189. -- assumes graph is undirected
  190. newPoints(dir, gsrc, dst, w, dead) AS (
  191. SELECT e.dir, e.gsrc AS gsrc, p.dst AS dst, e.w + p.w AS w, false AS dead
  192. FROM PathQ20 p JOIN toExplore e ON (e.dst = p.src)
  193. UNION ALL
  194. SELECT dir, gsrc, dst, w, dead OR EXISTS (SELECT * FROM toExplore e WHERE e.dir = o.dir AND e.gsrc = o.gsrc AND e.dst = o.dst) FROM ss o
  195. ),
  196. fullTable AS (
  197. SELECT distinct ON(dir, gsrc, dst) dir, gsrc, dst, w, dead
  198. FROM newPoints
  199. ORDER BY dir, gsrc, dst, w, dead DESC
  200. ),
  201. found AS (
  202. SELECT min(l.w + r.w) AS w
  203. FROM fullTable l, fullTable r
  204. WHERE l.dir = false AND r.dir = true AND l.dst = r.dst
  205. )
  206. SELECT dir,
  207. gsrc,
  208. dst,
  209. w,
  210. dead or (coalesce(t.w > (SELECT f.w/2 FROM found f), false)),
  211. e.iter + 1 AS iter
  212. FROM fullTable t, (SELECT iter FROM toExplore limit 1) e
  213. )
  214. ),
  215. ss (dir bool, gsrc bigint, dst bigint, w bigint, iter bigint) AS (
  216. SELECT dir, gsrc, dst, w, iter FROM shorts WHERE iter = (SELECT max(iter) FROM shorts)
  217. ),
  218. results(f bigint, t bigint, w bigint) AS (
  219. SELECT l.gsrc, r.gsrc, min(l.w + r.w)
  220. FROM ss l, ss r
  221. WHERE l.dir = false AND r.dir = true AND l.dst = r.dst
  222. GROUP BY l.gsrc, r.gsrc
  223. )
  224. SELECT t, w FROM results WHERE w = (SELECT min(w) FROM results) ORDER BY t LIMIT 20;
  225. */