q19.sql 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. \set city1Id 655::bigint
  2. \set city2Id 1138::bigint
  3. -- materialize=> \i q19.sql
  4. -- CREATE MATERIALIZED VIEW
  5. -- Time: 624.232 ms
  6. -- CREATE INDEX
  7. -- Time: 497.689 ms
  8. -- f | t | w
  9. -- ----------------+----------------+----
  10. -- 24189255818627 | 26388279072272 | 39
  11. -- (1 row)
  12. --
  13. -- Time: 8267.997 ms (00:08.268)
  14. --
  15. -- our simpler query
  16. --
  17. -- src | dst | w
  18. -- ----------------+----------------+----
  19. -- 24189255818627 | 26388279072272 | 39
  20. -- (1 row)
  21. --
  22. -- Time: 21601.377 ms (00:21.601)
  23. /* Q19. Interaction path between cities
  24. \set city1Id 608
  25. \set city2Id 1148
  26. */
  27. CREATE OR REPLACE VIEW PathQ19 AS
  28. WITH
  29. -- asymmetrize...
  30. knows_asymmetric AS (
  31. SELECT person1id, person2id
  32. FROM Person_knows_person
  33. WHERE person1id < person2id
  34. ),
  35. -- compute interaction scores (no interactions means we ignore that 'knows' relationship)
  36. weights(src, dst, w) AS (
  37. SELECT
  38. person1id AS src,
  39. person2id AS dst,
  40. greatest(round(40 - sqrt(count(*)))::bigint, 1) AS w
  41. FROM Message m1,
  42. Message m2,
  43. knows_asymmetric pp
  44. WHERE pp.person1id = least(m1.creatorpersonid, m2.creatorpersonid)
  45. AND pp.person2id = greatest(m1.creatorpersonid, m2.creatorpersonid)
  46. AND m1.parentmessageid = m2.messageid
  47. AND m1.creatorpersonid <> m2.creatorpersonid
  48. GROUP BY src, dst
  49. )
  50. -- resymmetrize
  51. SELECT src, dst, w FROM weights
  52. UNION ALL
  53. SELECT dst, src, w FROM weights;
  54. CREATE INDEX PathQ19_src ON PathQ19 (src);
  55. WITH
  56. srcs AS (SELECT id FROM Person WHERE locationcityid = :city1Id),
  57. dsts AS (SELECT id FROM Person WHERE locationcityid = :city2Id),
  58. completed_paths AS (
  59. WITH MUTUALLY RECURSIVE
  60. paths (src bigint, dst bigint, w double precision) AS (
  61. SELECT id AS src,
  62. id AS dst,
  63. 0::double precision AS w
  64. FROM srcs
  65. UNION
  66. SELECT paths1.src AS src,
  67. paths2.dst AS dst,
  68. paths1.w + paths2.w AS w
  69. FROM minimal_paths paths1
  70. JOIN PathQ19 paths2 -- step-transitive closure
  71. ON paths1.dst = paths2.src
  72. ),
  73. minimal_paths (src bigint, dst bigint, w double precision) AS (
  74. SELECT src, dst, min(w)
  75. FROM paths
  76. GROUP BY src, dst
  77. )
  78. SELECT src, dst, w
  79. FROM minimal_paths
  80. WHERE dst = ANY (SELECT id FROM dsts)
  81. )
  82. SELECT src, dst, w
  83. FROM completed_paths
  84. WHERE w = (SELECT min(w) FROM completed_paths);
  85. /*
  86. WITH MUTUALLY RECURSIVE
  87. srcs (f bigint) AS (SELECT id FROM Person WHERE locationcityid = :city1Id),
  88. dsts (t bigint) AS (SELECT id FROM Person WHERE locationcityid = :city2Id),
  89. shorts (dir bool, gsrc bigint, dst bigint, w double precision, dead bool, iter bigint) AS (
  90. (
  91. SELECT false, f, f, 0::double precision, false, 0 FROM srcs
  92. UNION ALL
  93. SELECT true, t, t, 0::double precision, false, 0 FROM dsts
  94. )
  95. UNION
  96. (
  97. WITH
  98. ss AS (SELECT * FROM shorts),
  99. toExplore AS (SELECT * FROM ss WHERE dead = false ORDER BY w LIMIT 1000),
  100. -- assumes graph is undirected
  101. newPoints(dir, gsrc, dst, w, dead) AS (
  102. SELECT e.dir, e.gsrc AS gsrc, p.dst AS dst, e.w + p.w AS w, false AS dead
  103. FROM PathQ19 p JOIN toExplore e ON (e.dst = p.src)
  104. UNION
  105. 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
  106. ),
  107. fullTable AS (
  108. SELECT DISTINCT ON(dir, gsrc, dst) dir, gsrc, dst, w, dead
  109. FROM newPoints
  110. ORDER BY dir, gsrc, dst, w, dead DESC
  111. ),
  112. found AS (
  113. SELECT min(l.w + r.w) AS w
  114. FROM fullTable l, fullTable r
  115. WHERE l.dir = false AND r.dir = true AND l.dst = r.dst
  116. )
  117. SELECT dir,
  118. gsrc,
  119. dst,
  120. w,
  121. dead or (coalesce(t.w > (SELECT f.w/2 FROM found f), false)),
  122. e.iter + 1 AS iter
  123. FROM fullTable t, (SELECT iter FROM toExplore LIMIT 1) e
  124. )
  125. ),
  126. ss (dir bool, gsrc bigint, dst bigint, w double precision, iter bigint) AS (
  127. SELECT dir, gsrc, dst, w, iter FROM shorts WHERE iter = (SELECT max(iter) FROM shorts)
  128. ),
  129. results (f bigint, t bigint, w double precision) AS (
  130. SELECT l.gsrc, r.gsrc, min(l.w + r.w)
  131. FROM ss l, ss r
  132. WHERE l.dir = false AND r.dir = true AND l.dst = r.dst
  133. GROUP BY l.gsrc, r.gsrc
  134. )
  135. SELECT * FROM results WHERE w = (SELECT min(w) FROM results) ORDER BY f, t;
  136. */