dbt Ecommerce ticketing

User Status

User Status model for ecommerce ticketing.

inferred

Blocks

user_status.sql · 58 lines
inferred
-- models/user_status.sql
{{ config(materialized='view') }}

SELECT 
        a.user_id,
        a.month,
        a.created_at,
        n.status as status_new,
        r.status as status_reactivated,
        c.status as status_churned,
        COALESCE(n.status, r.status, c.status) as status
      FROM (
        SELECT 
          DISTINCT user_id,
          TO_DATE(ts, 'YYYY-MM-DD') as created_at,
          TO_CHAR(ts, 'YYYY-MM') as month
        FROM ts_user_statuses
      ) a
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'new'
      ) n ON n.user_id = a.user_id AND n.month = a.month
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'reactivated'
      ) r ON r.user_id = a.user_id AND r.month = a.month
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'churned'
      ) c ON c.user_id = a.user_id AND c.month = a.month
      WHERE n.status IS NOT NULL OR r.status IS NOT NULL OR c.status IS NOT NULL
      ORDER BY 1, 2

# models/schema.yml
version: 2

models:
  - name: user_status
    columns:
      - name: user_id
      - name: status_date
      - name: status_month
      - name: status_new
      - name: status_reactivated
      - name: status_churned
      - name: status

Assumptions

  • materialized='view' is the default; no persist hint found.
  • schema.yml columns come from view dimensions; a primary_key dimension gets unique + not_null tests.
user_status.sql · 41 lines
source-preserved validation: parses
SELECT 
        a.user_id,
        a.month,
        a.created_at,
        n.status as status_new,
        r.status as status_reactivated,
        c.status as status_churned,
        COALESCE(n.status, r.status, c.status) as status
      FROM (
        SELECT 
          DISTINCT user_id,
          TO_DATE(ts, 'YYYY-MM-DD') as created_at,
          TO_CHAR(ts, 'YYYY-MM') as month
        FROM ts_user_statuses
      ) a
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'new'
      ) n ON n.user_id = a.user_id AND n.month = a.month
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'reactivated'
      ) r ON r.user_id = a.user_id AND r.month = a.month
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'churned'
      ) c ON c.user_id = a.user_id AND c.month = a.month
      WHERE n.status IS NOT NULL OR r.status IS NOT NULL OR c.status IS NOT NULL
      ORDER BY 1, 2
user_status.view.lkml · 115 lines
source-preserved
view: user_status {
  derived_table: {
    sql: SELECT 
        a.user_id,
        a.month,
        a.created_at,
        n.status as status_new,
        r.status as status_reactivated,
        c.status as status_churned,
        COALESCE(n.status, r.status, c.status) as status
      FROM (
        SELECT 
          DISTINCT user_id,
          TO_DATE(ts, 'YYYY-MM-DD') as created_at,
          TO_CHAR(ts, 'YYYY-MM') as month
        FROM ts_user_statuses
      ) a
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'new'
      ) n ON n.user_id = a.user_id AND n.month = a.month
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'reactivated'
      ) r ON r.user_id = a.user_id AND r.month = a.month
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'churned'
      ) c ON c.user_id = a.user_id AND c.month = a.month
      WHERE n.status IS NOT NULL OR r.status IS NOT NULL OR c.status IS NOT NULL
      ORDER BY 1, 2 ;;
  }

  dimension: user_id {
    type: string
    sql: ${TABLE}.user_id ;;
  }

  dimension: status_date {
    type: date
    sql: ${TABLE}.created_at ;;
  }

  dimension: status_month {
    type: string
    sql: ${TABLE}.month ;;
  }

  dimension: status_new {
    type: string
    sql: ${TABLE}.status_new ;;
  }

  dimension: status_reactivated {
    type: string
    sql: ${TABLE}.status_reactivated ;;
  }

  dimension: status_churned {
    type: string
    sql: ${TABLE}.status_churned ;;
  }

  dimension: status {
    type: string
    sql: ${TABLE}.status ;;
  }

  measure: count_users_status {
    type: number
    sql: CASE WHEN ${status} = 'churned' THEN -1.0 * ${count_users} ELSE ${count_users} END ;;
  }

  measure: count_users_new {
    type: count_distinct
    sql: CASE WHEN ${status} = 'new' THEN ${user_id} ELSE NULL END ;;
  }

  measure: count_users_reactivated {
    type: count_distinct
    sql: CASE WHEN ${status} = 'reactivated' THEN ${user_id} ELSE NULL END ;;
  }

  measure: count_users_churned {
    type: number
    sql: -1.0 * COUNT(DISTINCT CASE WHEN ${status} = 'churned' THEN ${user_id} ELSE NULL END) ;;
  }

  measure: count_users {
    type: count_distinct
    sql: ${user_id} ;;
  }

  measure: count_user_adj {
    type: number
    sql: ${count_users_new} + ${count_users_reactivated} + ${count_users_churned} ;;
  }

  measure: quick_ratio {
    type: number
    sql: 1.0 * (${count_users_new} + ${count_users_reactivated}) / NULLIF((-1.0 * ${count_users_churned}), 0) ;;
  }
}
user_status.view.lookml · 86 lines
inferred
- view: user_status
  derived_table:
    sql: SELECT 
        a.user_id,
        a.month,
        a.created_at,
        n.status as status_new,
        r.status as status_reactivated,
        c.status as status_churned,
        COALESCE(n.status, r.status, c.status) as status
      FROM (
        SELECT 
          DISTINCT user_id,
          TO_DATE(ts, 'YYYY-MM-DD') as created_at,
          TO_CHAR(ts, 'YYYY-MM') as month
        FROM ts_user_statuses
      ) a
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'new'
      ) n ON n.user_id = a.user_id AND n.month = a.month
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'reactivated'
      ) r ON r.user_id = a.user_id AND r.month = a.month
      LEFT JOIN (
        SELECT 
          user_id,
          TO_CHAR(ts, 'YYYY-MM') as month,
          status
        FROM ts_user_statuses
        WHERE status = 'churned'
      ) c ON c.user_id = a.user_id AND c.month = a.month
      WHERE n.status IS NOT NULL OR r.status IS NOT NULL OR c.status IS NOT NULL
      ORDER BY 1, 2
  fields:
  - dimension: user_id
    type: string
    sql: ${TABLE}.user_id
  - dimension: status_date
    type: date
    sql: ${TABLE}.created_at
  - dimension: status_month
    type: string
    sql: ${TABLE}.month
  - dimension: status_new
    type: string
    sql: ${TABLE}.status_new
  - dimension: status_reactivated
    type: string
    sql: ${TABLE}.status_reactivated
  - dimension: status_churned
    type: string
    sql: ${TABLE}.status_churned
  - dimension: status
    type: string
    sql: ${TABLE}.status
  - measure: count_users_status
    type: number
    sql: CASE WHEN ${status} = 'churned' THEN -1.0 * ${count_users} ELSE ${count_users} END
  - measure: count_users_new
    type: count_distinct
    sql: CASE WHEN ${status} = 'new' THEN ${user_id} ELSE NULL END
  - measure: count_users_reactivated
    type: count_distinct
    sql: CASE WHEN ${status} = 'reactivated' THEN ${user_id} ELSE NULL END
  - measure: count_users_churned
    type: number
    sql: -1.0 * COUNT(DISTINCT CASE WHEN ${status} = 'churned' THEN ${user_id} ELSE NULL END)
  - measure: count_users
    type: count_distinct
    sql: ${user_id}
  - measure: count_user_adj
    type: number
    sql: ${count_users_new} + ${count_users_reactivated} + ${count_users_churned}
  - measure: quick_ratio
    type: number
    sql: 1.0 * (${count_users_new} + ${count_users_reactivated}) / NULLIF((-1.0 * ${count_users_churned}), 0)

Contents

  • user_status.sql
  • user_status.sql
  • user_status.view.lkml
  • user_status.view.lookml