123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- # Copyright Materialize, Inc. and contributors. All rights reserved.
- #
- # Use of this software is governed by the Business Source License
- # included in the LICENSE file at the root of this repository.
- #
- # As of the Change Date specified in that file, in accordance with
- # the Business Source License, use of this software will be governed
- # by the Apache License, Version 2.0.
- statement ok
- CREATE TABLE events (
- -- event ID
- id int,
- -- when?
- event_time timestamp,
- -- who?
- user_id int,
- -- how much?
- worth decimal
- );
- statement ok
- CREATE MATERIALIZED VIEW event_session AS
- WITH MUTUALLY RECURSIVE
- -- Convert each value in events into a 5-minute long session
- make_session (user_id int4, session tsrange)
- AS (
- SELECT
- user_id, tsrange(event_time, event_time + '5 m'::INTERVAL) AS session
- FROM
- events
- ),
- -- Merge any overlapping/adjacent sessions
- merge_session (user_id int4, session tsrange)
- AS (
- SELECT
- DISTINCT user_id, l_session + r_session
- FROM
- (
- SELECT
- l.user_id AS user_id, l.session AS l_session, r.session AS r_session
- -- Base case is just the `make_session` relation
- FROM
- make_session AS l, make_session AS r
- WHERE
- l.user_id = r.user_id
- AND (l.session && r.session OR l.session -|- r.session)
- UNION ALL
- -- Further improve any merged sessions against any new sessions
- SELECT
- make_session.user_id, make_session.session, merge_session.session
- FROM
- make_session, merge_session
- WHERE
- -- ? @aalexandrov could this be
- -- reduce_session.user_id = merge_session.user_id
- -- AND (
- -- reduce_session.session && merge_session.session
- -- OR reduce_session.session -|- merge_session.session
- -- )
- -- if we do a cross join of reduce_session, merge_session
- make_session.user_id = merge_session.user_id
- AND (
- make_session.session && merge_session.session
- OR make_session.session -|- merge_session.session
- )
- )
- ),
- -- Keep only widest session that touches any given point in time
- reduce_session (user_id int4, session tsrange)
- AS (
- SELECT
- user_id, tsrange(lower, upper)
- FROM
- (
- SELECT
- user_id, min(lower) AS lower, upper
- FROM
- (
- SELECT
- user_id, lower(session), max(upper(session)) AS upper
- FROM
- merge_session
- GROUP BY
- user_id, lower(session)
- )
- GROUP BY
- user_id, upper
- )
- )
- SELECT
- *
- FROM
- reduce_session;
- statement ok
- CREATE MATERIALIZED VIEW user_session_worth AS
- SELECT
- user_id, id, count, upper(session) - lower(session) AS session_len, sum AS worth
- FROM
- (
- SELECT
- events.user_id, session, min(id) AS id, count(id), sum(worth)
- FROM
- events
- JOIN event_session ON
- events.user_id = event_session.user_id
- AND event_session.session @> events.event_time
- GROUP BY
- events.user_id, session
- );
- statement ok
- INSERT INTO events VALUES
- (1, '2021-01-01 10:00:00'::timestamp, 1, '0.01');
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:05:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 1 00:05:00 0.01
- statement ok
- INSERT INTO events VALUES
- (2, '2021-01-01 10:03:00'::timestamp, 1, '0.01');
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:08:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 2 00:08:00 0.02
- statement ok
- INSERT INTO events VALUES
- (3, '2021-01-01 10:06:00'::timestamp, 1, '1.00');
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 3 00:11:00 1.02
- statement ok
- INSERT INTO events VALUES
- (4, '2021-01-01 10:13:00'::timestamp, 1, '0.01');
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
- 1 ["2021-01-01 10:13:00","2021-01-01 10:18:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 3 00:11:00 1.02
- 1 4 1 00:05:00 0.01
- statement ok
- INSERT INTO events VALUES
- (5, '2021-01-01 10:15:00'::timestamp, 1, '0.01');
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
- 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 3 00:11:00 1.02
- 1 4 2 00:07:00 0.02
- statement ok
- INSERT INTO events VALUES
- (6, '2021-01-01 10:21:00'::timestamp, 1, '0.02');
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
- 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
- 1 ["2021-01-01 10:21:00","2021-01-01 10:26:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 3 00:11:00 1.02
- 1 4 2 00:07:00 0.02
- 1 6 1 00:05:00 0.02
- statement ok
- INSERT INTO events VALUES
- (7, '2021-01-01 10:02:00'::timestamp, 2, '1.00');
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
- 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
- 1 ["2021-01-01 10:21:00","2021-01-01 10:26:00")
- 2 ["2021-01-01 10:02:00","2021-01-01 10:07:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 3 00:11:00 1.02
- 1 4 2 00:07:00 0.02
- 1 6 1 00:05:00 0.02
- 2 7 1 00:05:00 1
- statement ok
- INSERT INTO events VALUES
- (8, '2021-01-01 10:04:00'::timestamp, 2, '1.00');
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
- 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
- 1 ["2021-01-01 10:21:00","2021-01-01 10:26:00")
- 2 ["2021-01-01 10:02:00","2021-01-01 10:09:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 3 00:11:00 1.02
- 1 4 2 00:07:00 0.02
- 1 6 1 00:05:00 0.02
- 2 7 2 00:07:00 2
- statement ok
- INSERT INTO events VALUES
- (9, '2021-01-01 10:17:00'::timestamp, 1, '0.01');
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
- 1 ["2021-01-01 10:13:00","2021-01-01 10:26:00")
- 2 ["2021-01-01 10:02:00","2021-01-01 10:09:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 3 00:11:00 1.02
- 1 4 4 00:13:00 0.05
- 2 7 2 00:07:00 2
- statement ok
- DELETE FROM events WHERE id = 9;
- query T
- SELECT concat(user_id, ' ', session) FROM event_session ORDER BY 1
- ----
- 1 ["2021-01-01 10:00:00","2021-01-01 10:11:00")
- 1 ["2021-01-01 10:13:00","2021-01-01 10:20:00")
- 1 ["2021-01-01 10:21:00","2021-01-01 10:26:00")
- 2 ["2021-01-01 10:02:00","2021-01-01 10:09:00")
- query T
- SELECT concat(user_id, ' ', id, ' ', count, ' ', session_len, ' ', worth) FROM user_session_worth ORDER BY 1;
- ----
- 1 1 3 00:11:00 1.02
- 1 4 2 00:07:00 0.02
- 1 6 1 00:05:00 0.02
- 2 7 2 00:07:00 2
|