session-window-wmr.slt 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. # Copyright Materialize, Inc. and contributors. All rights reserved.
  2. #
  3. # Use of this software is governed by the Business Source License
  4. # included in the LICENSE file at the root of this repository.
  5. #
  6. # As of the Change Date specified in that file, in accordance with
  7. # the Business Source License, use of this software will be governed
  8. # by the Apache License, Version 2.0.
  9. statement ok
  10. CREATE TABLE events (
  11. -- event ID
  12. id int,
  13. -- when?
  14. event_time timestamp,
  15. -- who?
  16. user_id int,
  17. -- how much?
  18. worth decimal
  19. );
  20. statement ok
  21. CREATE MATERIALIZED VIEW event_session AS
  22. WITH MUTUALLY RECURSIVE
  23. -- Convert each value in events into a 5-minute long session
  24. make_session (user_id int4, session tsrange)
  25. AS (
  26. SELECT
  27. user_id, tsrange(event_time, event_time + '5 m'::INTERVAL) AS session
  28. FROM
  29. events
  30. ),
  31. -- Merge any overlapping/adjacent sessions
  32. merge_session (user_id int4, session tsrange)
  33. AS (
  34. SELECT
  35. DISTINCT user_id, l_session + r_session
  36. FROM
  37. (
  38. SELECT
  39. l.user_id AS user_id, l.session AS l_session, r.session AS r_session
  40. -- Base case is just the `make_session` relation
  41. FROM
  42. make_session AS l, make_session AS r
  43. WHERE
  44. l.user_id = r.user_id
  45. AND (l.session && r.session OR l.session -|- r.session)
  46. UNION ALL
  47. -- Further improve any merged sessions against any new sessions
  48. SELECT
  49. make_session.user_id, make_session.session, merge_session.session
  50. FROM
  51. make_session, merge_session
  52. WHERE
  53. -- ? @aalexandrov could this be
  54. -- reduce_session.user_id = merge_session.user_id
  55. -- AND (
  56. -- reduce_session.session && merge_session.session
  57. -- OR reduce_session.session -|- merge_session.session
  58. -- )
  59. -- if we do a cross join of reduce_session, merge_session
  60. make_session.user_id = merge_session.user_id
  61. AND (
  62. make_session.session && merge_session.session
  63. OR make_session.session -|- merge_session.session
  64. )
  65. )
  66. ),
  67. -- Keep only widest session that touches any given point in time
  68. reduce_session (user_id int4, session tsrange)
  69. AS (
  70. SELECT
  71. user_id, tsrange(lower, upper)
  72. FROM
  73. (
  74. SELECT
  75. user_id, min(lower) AS lower, upper
  76. FROM
  77. (
  78. SELECT
  79. user_id, lower(session), max(upper(session)) AS upper
  80. FROM
  81. merge_session
  82. GROUP BY
  83. user_id, lower(session)
  84. )
  85. GROUP BY
  86. user_id, upper
  87. )
  88. )
  89. SELECT
  90. *
  91. FROM
  92. reduce_session;
  93. statement ok
  94. CREATE MATERIALIZED VIEW user_session_worth AS
  95. SELECT
  96. user_id, id, count, upper(session) - lower(session) AS session_len, sum AS worth
  97. FROM
  98. (
  99. SELECT
  100. events.user_id, session, min(id) AS id, count(id), sum(worth)
  101. FROM
  102. events
  103. JOIN event_session ON
  104. events.user_id = event_session.user_id
  105. AND event_session.session @> events.event_time
  106. GROUP BY
  107. events.user_id, session
  108. );
  109. statement ok
  110. INSERT INTO events VALUES
  111. (1, '2021-01-01 10:00:00'::timestamp, 1, '0.01');
  112. query T
  113. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  114. ----
  115. 1 ["2021-01-01 10:00:00","2021-01-01 10:05:00")
  116. query T
  117. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  118. ----
  119. 1 1 1 00:05:00 0.01
  120. statement ok
  121. INSERT INTO events VALUES
  122. (2, '2021-01-01 10:03:00'::timestamp, 1, '0.01');
  123. query T
  124. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  125. ----
  126. 1 ["2021-01-01 10:00:00","2021-01-01 10:08:00")
  127. query T
  128. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  129. ----
  130. 1 1 2 00:08:00 0.02
  131. statement ok
  132. INSERT INTO events VALUES
  133. (3, '2021-01-01 10:06:00'::timestamp, 1, '1.00');
  134. query T
  135. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  136. ----
  137. 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
  138. query T
  139. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  140. ----
  141. 1 1 3 00:11:00 1.02
  142. statement ok
  143. INSERT INTO events VALUES
  144. (4, '2021-01-01 10:13:00'::timestamp, 1, '0.01');
  145. query T
  146. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  147. ----
  148. 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
  149. 1 ["2021-01-01 10:13:00","2021-01-01 10:18:00")
  150. query T
  151. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  152. ----
  153. 1 1 3 00:11:00 1.02
  154. 1 4 1 00:05:00 0.01
  155. statement ok
  156. INSERT INTO events VALUES
  157. (5, '2021-01-01 10:15:00'::timestamp, 1, '0.01');
  158. query T
  159. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  160. ----
  161. 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
  162. 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
  163. query T
  164. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  165. ----
  166. 1 1 3 00:11:00 1.02
  167. 1 4 2 00:07:00 0.02
  168. statement ok
  169. INSERT INTO events VALUES
  170. (6, '2021-01-01 10:21:00'::timestamp, 1, '0.02');
  171. query T
  172. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  173. ----
  174. 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
  175. 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
  176. 1 ["2021-01-01 10:21:00","2021-01-01 10:26:00")
  177. query T
  178. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  179. ----
  180. 1 1 3 00:11:00 1.02
  181. 1 4 2 00:07:00 0.02
  182. 1 6 1 00:05:00 0.02
  183. statement ok
  184. INSERT INTO events VALUES
  185. (7, '2021-01-01 10:02:00'::timestamp, 2, '1.00');
  186. query T
  187. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  188. ----
  189. 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
  190. 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
  191. 1 ["2021-01-01 10:21:00","2021-01-01 10:26:00")
  192. 2 ["2021-01-01 10:02:00","2021-01-01 10:07:00")
  193. query T
  194. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  195. ----
  196. 1 1 3 00:11:00 1.02
  197. 1 4 2 00:07:00 0.02
  198. 1 6 1 00:05:00 0.02
  199. 2 7 1 00:05:00 1
  200. statement ok
  201. INSERT INTO events VALUES
  202. (8, '2021-01-01 10:04:00'::timestamp, 2, '1.00');
  203. query T
  204. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  205. ----
  206. 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
  207. 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
  208. 1 ["2021-01-01 10:21:00","2021-01-01 10:26:00")
  209. 2 ["2021-01-01 10:02:00","2021-01-01 10:09:00")
  210. query T
  211. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  212. ----
  213. 1 1 3 00:11:00 1.02
  214. 1 4 2 00:07:00 0.02
  215. 1 6 1 00:05:00 0.02
  216. 2 7 2 00:07:00 2
  217. statement ok
  218. INSERT INTO events VALUES
  219. (9, '2021-01-01 10:17:00'::timestamp, 1, '0.01');
  220. query T
  221. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  222. ----
  223. 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
  224. 1 ["2021-01-01 10:13:00","2021-01-01 10:26:00")
  225. 2 ["2021-01-01 10:02:00","2021-01-01 10:09:00")
  226. query T
  227. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  228. ----
  229. 1 1 3 00:11:00 1.02
  230. 1 4 4 00:13:00 0.05
  231. 2 7 2 00:07:00 2
  232. statement ok
  233. DELETE FROM events WHERE id = 9;
  234. query T
  235. SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
  236. ----
  237. 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
  238. 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
  239. 1 ["2021-01-01 10:21:00","2021-01-01 10:26:00")
  240. 2 ["2021-01-01 10:02:00","2021-01-01 10:09:00")
  241. query T
  242. SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
  243. ----
  244. 1 1 3 00:11:00 1.02
  245. 1 4 2 00:07:00 0.02
  246. 1 6 1 00:05:00 0.02
  247. 2 7 2 00:07:00 2