Skip to content

feat(dashboards): add session replay dashboard widget (9/11)#60496

Merged
MattPua merged 19 commits into
masterfrom
05-28-feat_dashboards_add_session_replay_dashboard_widget_and_batch_add_api
Jun 3, 2026
Merged

feat(dashboards): add session replay dashboard widget (9/11)#60496
MattPua merged 19 commits into
masterfrom
05-28-feat_dashboards_add_session_replay_dashboard_widget_and_batch_add_api

Conversation

@MattPua
Copy link
Copy Markdown
Member

@MattPua MattPua commented May 28, 2026

Problem

Session recordings belong on dashboards alongside error tracking. This PR adds the second list-style widget (session_replay_list) and generalizes backend config handling so multiple widget types can share the same create/update/run paths.

This PR is 9/11 in the dashboard widgets Graphite stack.

Depends on: PR 8 (#60524 — error tracking dashboard widget + shared tile orchestration)

Changes

  • session_replay_list widget — backend runner (reuses session recording list query + serializer shim), catalog/registry, config schema, preview, and frontend tile (component, edit modal, stories, tests)
  • Setup gating — catalog availability (session_replay_enabled) via WidgetRuntimeAvailabilityGuard + stacked vertical setup prompt when replay is disabled
  • Generic widget config API — replace error-tracking-only request serializers with JSONField + catalog schema hints so ET and SR configs don't cross-pollinate
  • run_widgets replay throttling — apply existing replay listing rate limits when batch-running session replay tiles (via get_replay_listing_throttle_error)
  • Shared frontend patterns with ET — edit modal uses shared tile builders/filter sections; config validation and form schemas deduped into shared helpers (widgetConfigValidation, widgetListFormSchema)
  • Single-patch save — session replay edit modal submits config + tile metadata in one onSave(config, buildWidgetTileMetadataPatch(...)) call, matching feat(dashboards): add error tracking dashboard widget (8/11) #60524
  • Backend validation parity — shared list-widget validators (limit, order, date range) with tests in test_run_widgets
  • Review follow-ups — aligned SR structure with ET (catalog defaults, kea typegen-safe modal logic, removed redundant property prefetch)

How did you test this code?

  • Agent: Jest for session replay widget, edit modal, preview, registry, and config validation
  • Agent: backend test_run_widgets for session replay runner and config validation cases
  • Verified preview renders with shared session recording Storybook fixtures

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

Add the skip-inkeep-docs label — no user-facing docs yet (feature flagged). Agent skill/docs land in #60516.

🤖 Agent context

  • Restacked onto feat(dashboards): add error tracking dashboard widget (8/11) #60524 after CLOSED #60495 was closed; branch name still references batch add API but batch create already exists on master — this PR is the session replay widget + multi-type config generalization
  • Load-more pagination intentionally omitted from widgets per product decision
  • Cursor agent assisted on review alignment, CI fixes, and single-patch save parity with ET

@MattPua MattPua changed the title feat(dashboards): add session replay dashboard widget and batch add API feat(dashboards): add session replay dashboard widget May 28, 2026
@github-actions
Copy link
Copy Markdown
Contributor

MCP UI Apps size report

App JS CSS
debug 474.9 KB 139.9 KB
action 349.4 KB 139.9 KB
action-list 357.2 KB 139.9 KB
cohort 348.5 KB 139.9 KB
cohort-list 356.2 KB 139.9 KB
error-details 369.9 KB 139.9 KB
error-issue 349.2 KB 139.9 KB
error-issue-list 357.2 KB 139.9 KB
experiment 353.7 KB 139.9 KB
experiment-list 358.0 KB 139.9 KB
experiment-results 355.8 KB 139.9 KB
feature-flag 434.3 KB 139.9 KB
feature-flag-list 438.8 KB 139.9 KB
feature-flag-testing 427.2 KB 139.9 KB
insight-actors 352.3 KB 139.9 KB
llm-costs 351.9 KB 139.9 KB
session-recording 350.2 KB 139.9 KB
session-summary 356.2 KB 139.9 KB
survey 350.0 KB 139.9 KB
survey-global-stats 354.8 KB 139.9 KB
survey-list 357.9 KB 139.9 KB
survey-stats 354.8 KB 139.9 KB
trace-span 348.8 KB 139.9 KB
trace-span-list 357.1 KB 139.9 KB
workflow 348.8 KB 139.9 KB
workflow-list 356.6 KB 139.9 KB
query-results 370.6 KB 139.9 KB
visual-review-snapshots 353.5 KB 139.9 KB

@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_widgetcard_shell_and_error_tracking_dashboard_widget branch from d06831b to e7e58c4 Compare May 28, 2026 17:23
@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_session_replay_dashboard_widget_and_batch_add_api branch from 2f88339 to 075aa24 Compare May 28, 2026 17:23
@tests-posthog
Copy link
Copy Markdown
Contributor

tests-posthog Bot commented May 28, 2026

⏭️ Skipped snapshot commit because branch advanced to 075aa24 while workflow was testing b357459.

The new commit will trigger its own snapshot update workflow.

If you expected this workflow to succeed: This can happen due to concurrent commits. To get a fresh workflow run, either:

  • Merge master into your branch, or
  • Push an empty commit: git commit --allow-empty -m 'trigger CI' && git push

@tests-posthog
Copy link
Copy Markdown
Contributor

tests-posthog Bot commented May 28, 2026

⏭️ Skipped snapshot commit because branch advanced to 694e167 while workflow was testing 075aa24.

The new commit will trigger its own snapshot update workflow.

If you expected this workflow to succeed: This can happen due to concurrent commits. To get a fresh workflow run, either:

  • Merge master into your branch, or
  • Push an empty commit: git commit --allow-empty -m 'trigger CI' && git push

@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_widgetcard_shell_and_error_tracking_dashboard_widget branch from e7e58c4 to c801c9e Compare May 28, 2026 18:51
@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_session_replay_dashboard_widget_and_batch_add_api branch from 694e167 to cb22c2b Compare May 28, 2026 18:51
@tests-posthog
Copy link
Copy Markdown
Contributor

tests-posthog Bot commented May 28, 2026

⏭️ Skipped snapshot commit because branch advanced to 4e2a8c2 while workflow was testing cb22c2b.

The new commit will trigger its own snapshot update workflow.

If you expected this workflow to succeed: This can happen due to concurrent commits. To get a fresh workflow run, either:

  • Merge master into your branch, or
  • Push an empty commit: git commit --allow-empty -m 'trigger CI' && git push

@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_widgetcard_shell_and_error_tracking_dashboard_widget branch from c801c9e to 325b2df Compare May 28, 2026 19:32
@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_session_replay_dashboard_widget_and_batch_add_api branch from 4e2a8c2 to 322cca9 Compare May 28, 2026 19:32
@MattPua MattPua mentioned this pull request May 28, 2026
@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_widgetcard_shell_and_error_tracking_dashboard_widget branch from 325b2df to b33da61 Compare May 28, 2026 19:35
@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_session_replay_dashboard_widget_and_batch_add_api branch from 322cca9 to 1fcb621 Compare May 28, 2026 19:35
@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_widgetcard_shell_and_error_tracking_dashboard_widget branch from b33da61 to 842c5d4 Compare May 28, 2026 19:39
@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_session_replay_dashboard_widget_and_batch_add_api branch from 1fcb621 to 7edd67d Compare May 28, 2026 19:39
@MattPua MattPua changed the title feat(dashboards): add session replay dashboard widget feat(dashboards): add session replay dashboard widget (8/10) May 28, 2026
@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_session_replay_dashboard_widget_and_batch_add_api branch from 7edd67d to bce78ef Compare May 28, 2026 19:43
@MattPua MattPua force-pushed the 05-28-feat_dashboards_add_widgetcard_shell_and_error_tracking_dashboard_widget branch from 842c5d4 to 74e73f0 Compare May 28, 2026 19:43
Comment thread products/dashboards/backend/widgets/session_replay_list.py
@posthog
Copy link
Copy Markdown
Contributor

posthog Bot commented Jun 2, 2026

Visual changes approved by @MattPua — baseline updated in f5de938.

View this run in PostHog

4 changed, 10 new.

Copy link
Copy Markdown
Contributor

@vdekrijger vdekrijger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Agreed with your comments that it would be nice if we can centralise some of the frontend / kea logic across widgets, but not a blocker for now and something that can be fixed in a follow up PR / when adding a 3rd widget type.

Comment thread products/dashboards/backend/api/dashboard.py Outdated
Comment thread products/dashboards/backend/api/test/test_run_widgets.py Outdated
Comment thread products/dashboards/backend/api/test/test_run_widgets.py Outdated
Comment thread products/dashboards/frontend/generated/api.zod.ts
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

ClickHouse migration SQL per cloud environment

  • unset
    • all
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64} - INTERVAL {lookback_days:Int32} DAY
              AND events.timestamp < {interval_end:DateTime64} + INTERVAL 1 DAY
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_unbounded ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_backfill ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              timestamp AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64}
              AND events.timestamp < {interval_end:DateTime64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64} - INTERVAL {lookback_days:Int32} DAY
              AND events.timestamp < {interval_end:DateTime64} + INTERVAL 1 DAY
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_unbounded ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_backfill ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              timestamp AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64}
              AND events.timestamp < {interval_end:DateTime64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export_backfill ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              timestamp AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64}
              AND events.timestamp < {interval_end:DateTime64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export_backfill ON CLUSTER posthog AS (
          SELECT
              pd.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  pd._timestamp < {interval_end:DateTime64}
                      AND NOT p._timestamp < {interval_end:DateTime64},
                  pd._timestamp,
                  p._timestamp < {interval_end:DateTime64}
                      AND NOT pd._timestamp < {interval_end:DateTime64},
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          FROM (
              SELECT
                  team_id,
                  distinct_id,
                  max(version) AS version,
                  argMax(person_id, person_distinct_id2.version) AS person_id,
                  argMax(_timestamp, person_distinct_id2.version) AS _timestamp
              FROM
                  person_distinct_id2
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  distinct_id
          ) AS pd
          INNER JOIN (
              SELECT
                  team_id,
                  id,
                  max(version) AS version,
                  argMax(properties, person.version) AS properties,
                  argMax(created_at, person.version) AS created_at,
                  argMax(_timestamp, person.version) AS _timestamp
              FROM
                  person
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  id
          ) AS p ON p.id = pd.person_id AND p.team_id = pd.team_id
          WHERE
              pd.team_id = {team_id:Int64}
              AND p.team_id = {team_id:Int64}
              AND (
                  pd._timestamp < {interval_end:DateTime64}
                  OR p._timestamp < {interval_end:DateTime64}
              )
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export_backfill ON CLUSTER posthog AS (
          SELECT
              pd.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  pd._timestamp < {interval_end:DateTime64}
                      AND NOT p._timestamp < {interval_end:DateTime64},
                  pd._timestamp,
                  p._timestamp < {interval_end:DateTime64}
                      AND NOT pd._timestamp < {interval_end:DateTime64},
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          FROM (
              SELECT
                  team_id,
                  distinct_id,
                  max(version) AS version,
                  argMax(person_id, person_distinct_id2.version) AS person_id,
                  argMax(_timestamp, person_distinct_id2.version) AS _timestamp
              FROM
                  person_distinct_id2
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  distinct_id
          ) AS pd
          INNER JOIN (
              SELECT
                  team_id,
                  id,
                  max(version) AS version,
                  argMax(properties, person.version) AS properties,
                  argMax(created_at, person.version) AS created_at,
                  argMax(_timestamp, person.version) AS _timestamp
              FROM
                  person
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  id
          ) AS p ON p.id = pd.person_id AND p.team_id = pd.team_id
          WHERE
              pd.team_id = {team_id:Int64}
              AND p.team_id = {team_id:Int64}
              AND (
                  pd._timestamp < {interval_end:DateTime64}
                  OR p._timestamp < {interval_end:DateTime64}
              )
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export_recent ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events_recent.distinct_id), cityHash64(events_recent.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              inserted_at AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events_recent
          PREWHERE
              events_recent.inserted_at >= {interval_start:DateTime64}
              AND events_recent.inserted_at < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export_backfill ON CLUSTER posthog AS (
          SELECT
              pd.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  pd._timestamp < {interval_end:DateTime64}
                      AND NOT p._timestamp < {interval_end:DateTime64},
                  pd._timestamp,
                  p._timestamp < {interval_end:DateTime64}
                      AND NOT pd._timestamp < {interval_end:DateTime64},
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          FROM (
              SELECT
                  team_id,
                  distinct_id,
                  max(version) AS version,
                  argMax(person_id, person_distinct_id2.version) AS person_id,
                  argMax(_timestamp, person_distinct_id2.version) AS _timestamp
              FROM
                  person_distinct_id2
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  distinct_id
          ) AS pd
          INNER JOIN (
              SELECT
                  team_id,
                  id,
                  max(version) AS version,
                  argMax(properties, person.version) AS properties,
                  argMax(created_at, person.version) AS created_at,
                  argMax(_timestamp, person.version) AS _timestamp
              FROM
                  person
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  id
          ) AS p ON p.id = pd.person_id AND p.team_id = pd.team_id
          WHERE
              pd.team_id = {team_id:Int64}
              AND p.team_id = {team_id:Int64}
              AND (
                  pd._timestamp < {interval_end:DateTime64}
                  OR p._timestamp < {interval_end:DateTime64}
              )
          ORDER BY
              _inserted_at
      )
  • US, EU, DEV
    • data
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64} - INTERVAL {lookback_days:Int32} DAY
              AND events.timestamp < {interval_end:DateTime64} + INTERVAL 1 DAY
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_unbounded ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_backfill ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              timestamp AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64}
              AND events.timestamp < {interval_end:DateTime64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64} - INTERVAL {lookback_days:Int32} DAY
              AND events.timestamp < {interval_end:DateTime64} + INTERVAL 1 DAY
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_unbounded ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {
      

…truncated. See the full SQL in the workflow logs.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

ClickHouse migration SQL per cloud environment

  • unset
    • all
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64} - INTERVAL {lookback_days:Int32} DAY
              AND events.timestamp < {interval_end:DateTime64} + INTERVAL 1 DAY
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_unbounded ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_backfill ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              timestamp AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64}
              AND events.timestamp < {interval_end:DateTime64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64} - INTERVAL {lookback_days:Int32} DAY
              AND events.timestamp < {interval_end:DateTime64} + INTERVAL 1 DAY
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_unbounded ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_backfill ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              timestamp AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64}
              AND events.timestamp < {interval_end:DateTime64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export_backfill ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              timestamp AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64}
              AND events.timestamp < {interval_end:DateTime64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export_backfill ON CLUSTER posthog AS (
          SELECT
              pd.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  pd._timestamp < {interval_end:DateTime64}
                      AND NOT p._timestamp < {interval_end:DateTime64},
                  pd._timestamp,
                  p._timestamp < {interval_end:DateTime64}
                      AND NOT pd._timestamp < {interval_end:DateTime64},
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          FROM (
              SELECT
                  team_id,
                  distinct_id,
                  max(version) AS version,
                  argMax(person_id, person_distinct_id2.version) AS person_id,
                  argMax(_timestamp, person_distinct_id2.version) AS _timestamp
              FROM
                  person_distinct_id2
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  distinct_id
          ) AS pd
          INNER JOIN (
              SELECT
                  team_id,
                  id,
                  max(version) AS version,
                  argMax(properties, person.version) AS properties,
                  argMax(created_at, person.version) AS created_at,
                  argMax(_timestamp, person.version) AS _timestamp
              FROM
                  person
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  id
          ) AS p ON p.id = pd.person_id AND p.team_id = pd.team_id
          WHERE
              pd.team_id = {team_id:Int64}
              AND p.team_id = {team_id:Int64}
              AND (
                  pd._timestamp < {interval_end:DateTime64}
                  OR p._timestamp < {interval_end:DateTime64}
              )
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export_backfill ON CLUSTER posthog AS (
          SELECT
              pd.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  pd._timestamp < {interval_end:DateTime64}
                      AND NOT p._timestamp < {interval_end:DateTime64},
                  pd._timestamp,
                  p._timestamp < {interval_end:DateTime64}
                      AND NOT pd._timestamp < {interval_end:DateTime64},
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          FROM (
              SELECT
                  team_id,
                  distinct_id,
                  max(version) AS version,
                  argMax(person_id, person_distinct_id2.version) AS person_id,
                  argMax(_timestamp, person_distinct_id2.version) AS _timestamp
              FROM
                  person_distinct_id2
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  distinct_id
          ) AS pd
          INNER JOIN (
              SELECT
                  team_id,
                  id,
                  max(version) AS version,
                  argMax(properties, person.version) AS properties,
                  argMax(created_at, person.version) AS created_at,
                  argMax(_timestamp, person.version) AS _timestamp
              FROM
                  person
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  id
          ) AS p ON p.id = pd.person_id AND p.team_id = pd.team_id
          WHERE
              pd.team_id = {team_id:Int64}
              AND p.team_id = {team_id:Int64}
              AND (
                  pd._timestamp < {interval_end:DateTime64}
                  OR p._timestamp < {interval_end:DateTime64}
              )
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export_recent ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events_recent.distinct_id), cityHash64(events_recent.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              inserted_at AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events_recent
          PREWHERE
              events_recent.inserted_at >= {interval_start:DateTime64}
              AND events_recent.inserted_at < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW persons_batch_export_backfill ON CLUSTER posthog AS (
          SELECT
              pd.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  pd._timestamp < {interval_end:DateTime64}
                      AND NOT p._timestamp < {interval_end:DateTime64},
                  pd._timestamp,
                  p._timestamp < {interval_end:DateTime64}
                      AND NOT pd._timestamp < {interval_end:DateTime64},
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          FROM (
              SELECT
                  team_id,
                  distinct_id,
                  max(version) AS version,
                  argMax(person_id, person_distinct_id2.version) AS person_id,
                  argMax(_timestamp, person_distinct_id2.version) AS _timestamp
              FROM
                  person_distinct_id2
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  distinct_id
          ) AS pd
          INNER JOIN (
              SELECT
                  team_id,
                  id,
                  max(version) AS version,
                  argMax(properties, person.version) AS properties,
                  argMax(created_at, person.version) AS created_at,
                  argMax(_timestamp, person.version) AS _timestamp
              FROM
                  person
              PREWHERE
                  team_id = {team_id:Int64}
              GROUP BY
                  team_id,
                  id
          ) AS p ON p.id = pd.person_id AND p.team_id = pd.team_id
          WHERE
              pd.team_id = {team_id:Int64}
              AND p.team_id = {team_id:Int64}
              AND (
                  pd._timestamp < {interval_end:DateTime64}
                  OR p._timestamp < {interval_end:DateTime64}
              )
          ORDER BY
              _inserted_at
      )
  • US, EU, DEV
    • data
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64} - INTERVAL {lookback_days:Int32} DAY
              AND events.timestamp < {interval_end:DateTime64} + INTERVAL 1 DAY
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_unbounded ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_backfill ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              timestamp AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64}
              AND events.timestamp < {interval_end:DateTime64}
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW persons_batch_export ON CLUSTER posthog AS (
          with new_persons as (
              select
                  id,
                  max(version) as version,
                  argMax(_timestamp, person.version) AS _timestamp2
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in (
                      select
                          id
                      from
                          person
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  id
              having
                  (
                      _timestamp2 >= {interval_start:DateTime64}
                      AND _timestamp2 < {interval_end:DateTime64}
                  )
          ),
          new_distinct_ids as (
              SELECT
                  argMax(person_id, person_distinct_id2.version) as person_id
              from
                  person_distinct_id2
              where
                  team_id = {team_id:Int64}
                  and distinct_id in (
                      select
                          distinct_id
                      from
                          person_distinct_id2
                      where
                          team_id = {team_id:Int64}
                          and _timestamp >= {interval_start:DateTime64}
                          AND _timestamp < {interval_end:DateTime64}
                  )
              group by
                  distinct_id
              having
                  (
                      argMax(_timestamp, person_distinct_id2.version) >= {interval_start:DateTime64}
                      AND argMax(_timestamp, person_distinct_id2.version) < {interval_end:DateTime64}
                  )
          ),
          all_new_persons as (
              select
                  id,
                  version
              from
                  new_persons
              UNION
              ALL
              select
                  id,
                  max(version)
              from
                  person
              where
                  team_id = {team_id:Int64}
                  and id in new_distinct_ids
              group by
                  id
          )
          select
              p.team_id AS team_id,
              pd.distinct_id AS distinct_id,
              toString(p.id) AS person_id,
              p.properties AS properties,
              pd.version AS person_distinct_id_version,
              p.version AS person_version,
              p.created_at AS created_at,
              multiIf(
                  (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  ),
                  pd._timestamp,
                  (
                      p._timestamp >= {interval_start:DateTime64}
                      AND p._timestamp < {interval_end:DateTime64}
                  )
                  AND NOT (
                      pd._timestamp >= {interval_start:DateTime64}
                      AND pd._timestamp < {interval_end:DateTime64}
                  ),
                  p._timestamp,
                  least(p._timestamp, pd._timestamp)
              ) AS _inserted_at
          from
              person p
              INNER JOIN (
                  SELECT
                      distinct_id,
                      max(version) AS version,
                      argMax(person_id, person_distinct_id2.version) AS person_id2,
                      argMax(_timestamp, person_distinct_id2.version) AS _timestamp
                  FROM
                      person_distinct_id2
                  WHERE
                      team_id = {team_id:Int64}
                      and person_id IN (
                          select
                              id
                          from
                              all_new_persons
                      )
                  GROUP BY
                      distinct_id
              ) AS pd ON p.id = pd.person_id2
          where
              team_id = {team_id:Int64}
              and (id, version) in all_new_persons
          ORDER BY
              _inserted_at
      )
      CREATE OR REPLACE VIEW events_batch_export ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {interval_start:DateTime64}
              AND COALESCE(events.inserted_at, events._timestamp) < {interval_end:DateTime64}
          WHERE
              team_id = {team_id:Int64}
              AND events.timestamp >= {interval_start:DateTime64} - INTERVAL {lookback_days:Int32} DAY
              AND events.timestamp < {interval_end:DateTime64} + INTERVAL 1 DAY
              AND (length({include_events:Array(String)}) = 0 OR event IN {include_events:Array(String)})
              AND (length({exclude_events:Array(String)}) = 0 OR event NOT IN {exclude_events:Array(String)})
          ORDER BY
              _inserted_at, event
          SETTINGS optimize_aggregation_in_order=1
      )
      CREATE OR REPLACE VIEW events_batch_export_unbounded ON CLUSTER posthog AS (
          SELECT DISTINCT ON (team_id, event, cityHash64(events.distinct_id), cityHash64(events.uuid))
              team_id AS team_id,
              timestamp AS timestamp,
              event AS event,
              distinct_id AS distinct_id,
              toString(uuid) AS uuid,
              COALESCE(inserted_at, _timestamp) AS _inserted_at,
              created_at AS created_at,
              elements_chain AS elements_chain,
              toString(person_id) AS person_id,
              nullIf(properties, '') AS properties,
              nullIf(person_properties, '') AS person_properties,
              nullIf(JSONExtractString(properties, '$set'), '') AS set,
              nullIf(JSONExtractString(properties, '$set_once'), '') AS set_once
          FROM
              events
          PREWHERE
              COALESCE(events.inserted_at, events._timestamp) >= {
      

…truncated. See the full SQL in the workflow logs.

MattPua and others added 17 commits June 3, 2026 12:56
Restack onto error tracking widget branch: merge catalog/registry,
align edit modal with kea pattern, and sync backend widget catalog.

Co-authored-by: Cursor <cursoragent@cursor.com>
Share widget list limit and orderDirection schema, drop backend error_tracking
alias, apply replay listing throttles on run_widgets, and stop ET config
serializer from polluting session replay widget payloads.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
… logic

Co-authored-by: Cursor <cursoragent@cursor.com>
Share tile metadata save logic, kea builders, and tile details UI
across session replay and error tracking edit modals; align session
replay modal structure with error tracking and inline loading skeleton count.

Co-authored-by: Cursor <cursoragent@cursor.com>
session replay modal still referenced deleted editWidgetModalTileBuilders barrel

Co-authored-by: Cursor <cursoragent@cursor.com>
…erns

Reuse shared edit modal builders, form schema, filters section, and backend
validation tests. Drop redundant property-loading useEffect and utils helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
Extract shared list-widget validation (frontend and backend), inline edit
modal reducers for kea-typegen, dedupe form schemas, and align catalog with ET.

Co-authored-by: Cursor <cursoragent@cursor.com>
Extract run_recordings_list_query from SessionRecordingViewSet.list so
the session replay widget calls the same fetch+serialize path instead
of duplicating serializer wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use onSave(config, metadataPatch) after ET branch removed the separate
metadata helper.
Edit session replay widget modal connects to filterTestAccountsDefaultsLogic
for the test-account filter section; mirror ET story seeding.
…ranch

Keep session_replay_list analytics coverage here where the widget type
is registered; ET branch only tests error_tracking_list.
Use SESSION_REPLAY_LIST_WIDGET_TYPE for replay throttle checks and move
session replay test imports to module scope.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use a polymorphic OpenAPI field for widget config instead of JSONField so
generated zod/types expose error tracking and session replay config shapes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread products/dashboards/backend/widget_registry.py
12 updated
Run: fc554141-b97e-47fb-91e6-8e63f15f8568

Co-authored-by: MattPua <3376526+MattPua@users.noreply.github.com>
@tests-posthog
Copy link
Copy Markdown
Contributor

tests-posthog Bot commented Jun 3, 2026

⏭️ Skipped snapshot commit because branch advanced to f5de938 while workflow was testing 6835fea.

The new commit will trigger its own snapshot update workflow.

If you expected this workflow to succeed: This can happen due to concurrent commits. To get a fresh workflow run, either:

  • Merge master into your branch, or
  • Push an empty commit: git commit --allow-empty -m 'trigger CI' && git push

Co-authored-by: Cursor <cursoragent@cursor.com>
@deployment-status-posthog
Copy link
Copy Markdown

deployment-status-posthog Bot commented Jun 3, 2026

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-06-03 18:38 UTC Run
prod-us ✅ Deployed 2026-06-03 18:52 UTC Run
prod-eu ✅ Deployed 2026-06-03 18:56 UTC Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants