dbt
Saas hospitality
Conversations Facts
Conversations Facts model for saas hospitality.
inferred
Blocks
conversations_facts.sql · 59 lines
inferred
-- models/conversations_facts.sql
{{ config(materialized='view') }}
SELECT
conversation_id
, COUNT(*) AS number_messages
, SUM(case m.sender_type when 'Guest' then 1 else 0 end) AS number_guest_messages
, SUM(case m.sender_type when 'User' then 1 else 0 end) AS number_user_messages
, MIN(m.created_at) AS first_message_sent
, MAX(m.created_at) AS last_message_sent
, MIN(CASE WHEN y.message_sequence_number > 1 THEN y.elapsed_response_time ELSE NULL END) AS first_message_response_time_seconds
, AVG(elapsed_response_time) AS average_of_messages_response_time_seconds
, SUM(elapsed_response_time) AS total_response_time_seconds
FROM messages AS m
LEFT JOIN
(SELECT
*
, EXTRACT(EPOCH FROM (x.created_at - x.previous_message_sent)) as elapsed_response_time
FROM
(SELECT
m.id
, m.created_at
, ROW_NUMBER() OVER(PARTITION BY m.conversation_id ORDER BY m.created_at) AS message_sequence_number
, CASE WHEN(m.sender_type != LAG(m.sender_type) OVER(PARTITION BY m.conversation_id ORDER BY m.created_at))
THEN (LAG(m.created_at) OVER(PARTITION BY m.conversation_id ORDER BY m.created_at))
ELSE NULL
END as previous_message_sent
FROM messages m
WHERE m.type = 'Messages::PlaceholderAdHoc'
AND m.sender_type != 'PlaceholderSenderType'
) x) y ON y.id = m.id
WHERE m.type = 'Messages::PlaceholderAdHoc'
GROUP BY 1
# models/schema.yml
version: 2
models:
- name: conversations_facts
columns:
- name: conversation_id
tests:
- unique
- not_null
- name: number_messages
- name: number_guest_messages
- name: number_user_messages
- name: number_messages_tier
- name: total_response_time_seconds
- name: total_response_time_seconds_tier
- name: average_of_messages_response_time_seconds
- name: average_of_messages_response_time_minutes
- name: average_message_response_time_minutes_tier
- name: first_message_sent
- name: last_message_sent
- name: first_message_response_time_seconds
- name: first_message_response_time_minutes
- name: first_message_response_time_seconds_tier
- name: first_message_response_time_minutes_tier
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.
conversations_facts.sql · 30 lines
source-preserved
validation: parses
SELECT
conversation_id
, COUNT(*) AS number_messages
, SUM(case m.sender_type when 'Guest' then 1 else 0 end) AS number_guest_messages
, SUM(case m.sender_type when 'User' then 1 else 0 end) AS number_user_messages
, MIN(m.created_at) AS first_message_sent
, MAX(m.created_at) AS last_message_sent
, MIN(CASE WHEN y.message_sequence_number > 1 THEN y.elapsed_response_time ELSE NULL END) AS first_message_response_time_seconds
, AVG(elapsed_response_time) AS average_of_messages_response_time_seconds
, SUM(elapsed_response_time) AS total_response_time_seconds
FROM messages AS m
LEFT JOIN
(SELECT
*
, EXTRACT(EPOCH FROM (x.created_at - x.previous_message_sent)) as elapsed_response_time
FROM
(SELECT
m.id
, m.created_at
, ROW_NUMBER() OVER(PARTITION BY m.conversation_id ORDER BY m.created_at) AS message_sequence_number
, CASE WHEN(m.sender_type != LAG(m.sender_type) OVER(PARTITION BY m.conversation_id ORDER BY m.created_at))
THEN (LAG(m.created_at) OVER(PARTITION BY m.conversation_id ORDER BY m.created_at))
ELSE NULL
END as previous_message_sent
FROM messages m
WHERE m.type = 'Messages::PlaceholderAdHoc'
AND m.sender_type != 'PlaceholderSenderType'
) x) y ON y.id = m.id
WHERE m.type = 'Messages::PlaceholderAdHoc'
GROUP BY 1
conversations_facts.view.lkml · 144 lines
inferred
view: conversations_facts {
derived_table: {
sql: SELECT
conversation_id
, COUNT(*) AS number_messages
, SUM(case m.sender_type when 'Guest' then 1 else 0 end) AS number_guest_messages
, SUM(case m.sender_type when 'User' then 1 else 0 end) AS number_user_messages
, MIN(m.created_at) AS first_message_sent
, MAX(m.created_at) AS last_message_sent
, MIN(CASE WHEN y.message_sequence_number > 1 THEN y.elapsed_response_time ELSE NULL END) AS first_message_response_time_seconds
, AVG(elapsed_response_time) AS average_of_messages_response_time_seconds
, SUM(elapsed_response_time) AS total_response_time_seconds
FROM messages AS m
LEFT JOIN
(SELECT
*
, EXTRACT(EPOCH FROM (x.created_at - x.previous_message_sent)) as elapsed_response_time
FROM
(SELECT
m.id
, m.created_at
, ROW_NUMBER() OVER(PARTITION BY m.conversation_id ORDER BY m.created_at) AS message_sequence_number
, CASE WHEN(m.sender_type != LAG(m.sender_type) OVER(PARTITION BY m.conversation_id ORDER BY m.created_at))
THEN (LAG(m.created_at) OVER(PARTITION BY m.conversation_id ORDER BY m.created_at))
ELSE NULL
END as previous_message_sent
FROM messages m
WHERE m.type = 'Messages::PlaceholderAdHoc'
AND m.sender_type != 'PlaceholderSenderType'
) x) y ON y.id = m.id
WHERE m.type = 'Messages::PlaceholderAdHoc'
GROUP BY 1 ;;
}
dimension: conversation_id {
primary_key: yes
sql: ${TABLE}.conversation_id ;;
}
dimension: number_messages {
type: number
sql: ${TABLE}.number_messages ;;
}
dimension: number_guest_messages {
type: number
sql: ${TABLE}.number_guest_messages ;;
}
dimension: number_user_messages {
type: number
sql: ${TABLE}.number_user_messages ;;
}
dimension: number_messages_tier {
type: tier
sql: ${number_messages} ;;
}
dimension: total_response_time_seconds {
type: number
sql: ${TABLE}.total_response_time_seconds ;;
}
dimension: total_response_time_seconds_tier {
type: tier
sql: ${total_response_time_seconds} ;;
}
dimension: average_of_messages_response_time_seconds {
type: number
sql: ${TABLE}.average_of_messages_response_time_seconds ;;
}
dimension: average_of_messages_response_time_minutes {
type: number
sql: ${average_of_messages_response_time_seconds}/60 ;;
}
dimension: average_message_response_time_minutes_tier {
type: tier
sql: ${average_of_messages_response_time_minutes} ;;
}
dimension: first_message_sent {
type: time
sql: ${TABLE}.first_message_sent ;;
}
dimension: last_message_sent {
type: time
sql: ${TABLE}.last_message_sent ;;
}
dimension: first_message_response_time_seconds {
type: number
sql: ${TABLE}.first_message_response_time_seconds ;;
}
dimension: first_message_response_time_minutes {
type: number
sql: ${first_message_response_time_seconds}/60 ;;
}
dimension: first_message_response_time_seconds_tier {
type: tier
sql: ${first_message_response_time_seconds} ;;
}
dimension: first_message_response_time_minutes_tier {
type: tier
sql: ${first_message_response_time_minutes} ;;
}
measure: avg_first_message_response_time_seconds {
type: avg
sql: ${first_message_response_time_seconds} ;;
}
measure: avg_first_message_response_time_minutes {
type: avg
sql: ${first_message_response_time_minutes} ;;
}
measure: avg_message_response_time_minutes {
type: avg
sql: ${average_of_messages_response_time_minutes} ;;
}
measure: avg_number_messages {
type: avg
sql: ${number_messages} ;;
}
measure: avg_number_guest_messages {
type: avg
sql: ${number_guest_messages} ;;
}
measure: avg_number_user_messages {
type: avg
sql: ${number_user_messages} ;;
}
}
conversations_facts.view.lookml · 99 lines
source-preserved
- view: conversations_facts
derived_table:
sql: SELECT
conversation_id
, COUNT(*) AS number_messages
, SUM(case m.sender_type when 'Guest' then 1 else 0 end) AS number_guest_messages
, SUM(case m.sender_type when 'User' then 1 else 0 end) AS number_user_messages
, MIN(m.created_at) AS first_message_sent
, MAX(m.created_at) AS last_message_sent
, MIN(CASE WHEN y.message_sequence_number > 1 THEN y.elapsed_response_time ELSE NULL END) AS first_message_response_time_seconds
, AVG(elapsed_response_time) AS average_of_messages_response_time_seconds
, SUM(elapsed_response_time) AS total_response_time_seconds
FROM messages AS m
LEFT JOIN
(SELECT
*
, EXTRACT(EPOCH FROM (x.created_at - x.previous_message_sent)) as elapsed_response_time
FROM
(SELECT
m.id
, m.created_at
, ROW_NUMBER() OVER(PARTITION BY m.conversation_id ORDER BY m.created_at) AS message_sequence_number
, CASE WHEN(m.sender_type != LAG(m.sender_type) OVER(PARTITION BY m.conversation_id ORDER BY m.created_at))
THEN (LAG(m.created_at) OVER(PARTITION BY m.conversation_id ORDER BY m.created_at))
ELSE NULL
END as previous_message_sent
FROM messages m
WHERE m.type = 'Messages::PlaceholderAdHoc'
AND m.sender_type != 'PlaceholderSenderType'
) x) y ON y.id = m.id
WHERE m.type = 'Messages::PlaceholderAdHoc'
GROUP BY 1
fields:
- dimension: conversation_id
primary_key: true
sql: ${TABLE}.conversation_id
- dimension: number_messages
type: number
sql: ${TABLE}.number_messages
- dimension: number_guest_messages
type: number
sql: ${TABLE}.number_guest_messages
- dimension: number_user_messages
type: number
sql: ${TABLE}.number_user_messages
- dimension: number_messages_tier
type: tier
sql: ${number_messages}
- dimension: total_response_time_seconds
type: number
sql: ${TABLE}.total_response_time_seconds
- dimension: total_response_time_seconds_tier
type: tier
sql: ${total_response_time_seconds}
- dimension: average_of_messages_response_time_seconds
type: number
sql: ${TABLE}.average_of_messages_response_time_seconds
- dimension: average_of_messages_response_time_minutes
type: number
sql: ${average_of_messages_response_time_seconds}/60
- dimension: average_message_response_time_minutes_tier
type: tier
sql: ${average_of_messages_response_time_minutes}
- dimension: first_message_sent
type: time
sql: ${TABLE}.first_message_sent
- dimension: last_message_sent
type: time
sql: ${TABLE}.last_message_sent
- dimension: first_message_response_time_seconds
type: number
sql: ${TABLE}.first_message_response_time_seconds
- dimension: first_message_response_time_minutes
type: number
sql: ${first_message_response_time_seconds}/60
- dimension: first_message_response_time_seconds_tier
type: tier
sql: ${first_message_response_time_seconds}
- dimension: first_message_response_time_minutes_tier
type: tier
sql: ${first_message_response_time_minutes}
- measure: avg_first_message_response_time_seconds
type: avg
sql: ${first_message_response_time_seconds}
- measure: avg_first_message_response_time_minutes
type: avg
sql: ${first_message_response_time_minutes}
- measure: avg_message_response_time_minutes
type: avg
sql: ${average_of_messages_response_time_minutes}
- measure: avg_number_messages
type: avg
sql: ${number_messages}
- measure: avg_number_guest_messages
type: avg
sql: ${number_guest_messages}
- measure: avg_number_user_messages
type: avg
sql: ${number_user_messages}
Contents
- conversations_facts.sql
- conversations_facts.sql
- conversations_facts.view.lkml
- conversations_facts.view.lookml