sql/moz-fx-data-shared-prod/stripe_external/subscriptions_changelog_v1/query.sql (298 lines of code) (raw):
WITH subscriptions_history AS (
SELECT
-- Synthesize a primary key column to make identifying rows and doing joins easier.
CONCAT(id, '-', FORMAT_TIMESTAMP('%FT%H:%M:%E6S', _fivetran_start)) AS id,
id AS subscription_id,
_fivetran_synced,
_fivetran_start,
_fivetran_active,
billing_cycle_anchor,
cancel_at,
cancel_at_period_end,
canceled_at,
-- `billing` was renamed `collection_method`.
COALESCE(collection_method, billing) AS collection_method,
created,
current_period_end,
current_period_start,
customer_id,
days_until_due,
default_payment_method_id,
default_source_id,
ended_at,
latest_invoice_id,
PARSE_JSON(metadata) AS metadata,
pending_setup_intent_id,
start_date,
status,
trial_end,
trial_start,
FROM
`moz-fx-data-shared-prod`.stripe_external.subscription_history_v1
),
new_subscriptions_history AS (
{% if is_init() %}
SELECT
*
FROM
subscriptions_history
{% else %}
WITH latest_subscriptions_changelog AS (
SELECT
subscription.id AS subscription_id,
MAX(`timestamp`) AS max_timestamp
FROM
`moz-fx-data-shared-prod`.stripe_external.subscriptions_changelog_v1
GROUP BY
subscription.id
)
SELECT
subscriptions_history.*
FROM
subscriptions_history
LEFT JOIN
latest_subscriptions_changelog
USING (subscription_id)
WHERE
subscriptions_history._fivetran_start > latest_subscriptions_changelog.max_timestamp
OR latest_subscriptions_changelog.max_timestamp IS NULL
{% endif %}
),
subscription_items AS (
SELECT
id,
created,
PARSE_JSON(metadata) AS metadata,
plan_id,
quantity,
subscription_id,
FROM
`moz-fx-data-shared-prod`.stripe_external.subscription_item_v1
QUALIFY
-- With how SubPlat currently works each Stripe subscription should only have
-- one subscription item, and we enforce that so the ETL can rely on it.
1 = COUNT(*) OVER (PARTITION BY subscription_id)
),
products AS (
SELECT
id,
created,
description,
PARSE_JSON(metadata) AS metadata,
name,
statement_descriptor,
updated,
FROM
`moz-fx-data-shared-prod`.stripe_external.product_v1
),
plans AS (
SELECT
id,
aggregate_usage,
amount,
billing_scheme,
created,
currency,
`interval`,
interval_count,
PARSE_JSON(metadata) AS metadata,
nickname,
product_id,
tiers_mode,
trial_period_days,
usage_type,
FROM
`moz-fx-data-shared-prod`.stripe_external.plan_v1
),
subscriptions_history_with_plan_metadata AS (
SELECT
*,
JSON_VALUE(metadata.previous_plan_id) AS previous_plan_id,
LEAD(JSON_VALUE(metadata.previous_plan_id)) OVER (
PARTITION BY
subscription_id
ORDER BY
_fivetran_start
) AS lead_previous_plan_id
FROM
new_subscriptions_history
),
subscriptions_history_with_end_plan_ids AS (
-- Determine the plan ID for the last record in each time span that a subscription had a particular plan.
SELECT
subscriptions_history.*,
CASE
-- The latest history record gets the current plan from its associated subscription item.
WHEN subscriptions_history._fivetran_active
THEN subscription_items.plan_id
-- A new `previous_plan_id` value means the previous record was the last record with that plan.
WHEN subscriptions_history.lead_previous_plan_id IS DISTINCT FROM subscriptions_history.previous_plan_id
THEN subscriptions_history.lead_previous_plan_id
ELSE NULL
END AS end_plan_id
FROM
subscriptions_history_with_plan_metadata AS subscriptions_history
JOIN
subscription_items
ON subscriptions_history.subscription_id = subscription_items.subscription_id
),
subscriptions_history_with_plan_ids AS (
-- Fill in `plan_id` by getting the next `end_plan_id`.
SELECT
*,
FIRST_VALUE(end_plan_id IGNORE NULLS) OVER (
PARTITION BY
subscription_id
ORDER BY
_fivetran_start
ROWS BETWEEN
CURRENT ROW
AND UNBOUNDED FOLLOWING
) AS plan_id
FROM
subscriptions_history_with_end_plan_ids
),
subscriptions_history_tax_rates AS (
SELECT
subscriptions_history.id AS subscription_history_id,
ARRAY_AGG(
STRUCT(
subscription_tax_rates.tax_rate_id AS id,
tax_rates.created,
tax_rates.description,
tax_rates.display_name,
tax_rates.inclusive,
tax_rates.jurisdiction,
PARSE_JSON(tax_rates.metadata) AS metadata,
tax_rates.percentage
)
ORDER BY
tax_rates.created
) AS tax_rates
FROM
new_subscriptions_history AS subscriptions_history
JOIN
`moz-fx-data-shared-prod`.stripe_external.subscription_tax_rate_v1 AS subscription_tax_rates
ON subscriptions_history.subscription_id = subscription_tax_rates.subscription_id
JOIN
`moz-fx-data-shared-prod`.stripe_external.tax_rate_v1 AS tax_rates
ON subscription_tax_rates.tax_rate_id = tax_rates.id
AND subscriptions_history._fivetran_start >= tax_rates.created
GROUP BY
subscriptions_history.id
),
subscriptions_history_latest_discounts AS (
SELECT
subscriptions_history.id AS subscription_history_id,
ARRAY_AGG(
STRUCT(
subscription_discounts.id,
STRUCT(
subscription_discounts.coupon_id AS id,
coupons.amount_off,
coupons.created,
coupons.currency,
coupons.duration,
coupons.duration_in_months,
PARSE_JSON(coupons.metadata) AS metadata,
coupons.name,
coupons.percent_off,
coupons.redeem_by
) AS coupon,
subscription_discounts.`end`,
subscription_discounts.invoice_id,
subscription_discounts.invoice_item_id,
subscription_discounts.promotion_code AS promotion_code_id,
subscription_discounts.start
)
ORDER BY
subscription_discounts.start DESC
LIMIT
1
)[SAFE_ORDINAL(1)] AS discount
FROM
new_subscriptions_history AS subscriptions_history
JOIN
`moz-fx-data-shared-prod`.stripe_external.subscription_discount_v2 AS subscription_discounts
ON subscriptions_history.subscription_id = subscription_discounts.subscription_id
AND subscriptions_history._fivetran_start >= subscription_discounts.start
AND (
subscriptions_history._fivetran_start < subscription_discounts.`end`
OR subscription_discounts.`end` IS NULL
)
JOIN
`moz-fx-data-shared-prod`.stripe_external.coupon_v1 AS coupons
ON subscription_discounts.coupon_id = coupons.id
GROUP BY
subscriptions_history.id
)
SELECT
subscriptions_history.id,
subscriptions_history._fivetran_start AS `timestamp`,
subscriptions_history._fivetran_synced AS synced_at,
STRUCT(
subscriptions_history.subscription_id AS id,
subscriptions_history.billing_cycle_anchor,
subscriptions_history.cancel_at,
subscriptions_history.cancel_at_period_end,
subscriptions_history.canceled_at,
subscriptions_history.collection_method,
subscriptions_history.created,
subscriptions_history.current_period_end,
subscriptions_history.current_period_start,
subscriptions_history.customer_id,
subscriptions_history.days_until_due,
subscriptions_history.default_payment_method_id,
subscriptions_history.default_source_id,
COALESCE(subscriptions_history_tax_rates.tax_rates, []) AS default_tax_rates,
subscriptions_history_latest_discounts.discount,
subscriptions_history.ended_at,
-- While SubPlat currently only allows subscriptions to have a single item,
-- they're planning to allow subscriptions with multiple items at some point.
[
STRUCT(
subscription_items.id,
subscription_items.created,
subscription_items.metadata,
STRUCT(
subscriptions_history.plan_id AS id,
plans.aggregate_usage,
plans.amount,
plans.billing_scheme,
plans.created,
plans.currency,
plans.`interval`,
plans.interval_count,
plans.metadata,
plans.nickname,
STRUCT(
plans.product_id AS id,
products.created,
products.description,
products.metadata,
products.name,
products.statement_descriptor,
products.updated
) AS product,
plans.tiers_mode,
plans.trial_period_days,
plans.usage_type
) AS plan,
subscription_items.quantity
)
] AS items,
subscriptions_history.latest_invoice_id,
subscriptions_history.metadata,
subscriptions_history.pending_setup_intent_id,
subscriptions_history.start_date,
subscriptions_history.status,
subscriptions_history.trial_end,
subscriptions_history.trial_start
) AS subscription
FROM
subscriptions_history_with_plan_ids AS subscriptions_history
JOIN
subscription_items
ON subscriptions_history.subscription_id = subscription_items.subscription_id
LEFT JOIN
plans
ON subscriptions_history.plan_id = plans.id
LEFT JOIN
products
ON plans.product_id = products.id
LEFT JOIN
subscriptions_history_tax_rates
ON subscriptions_history.id = subscriptions_history_tax_rates.subscription_history_id
LEFT JOIN
subscriptions_history_latest_discounts
ON subscriptions_history.id = subscriptions_history_latest_discounts.subscription_history_id