diff --git a/models/marts/reporting/rep_shipping__cohort_analysis.sql b/models/marts/reporting/rep_shipping__cohort_analysis.sql new file mode 100644 index 0000000..a35ffac --- /dev/null +++ b/models/marts/reporting/rep_shipping__cohort_analysis.sql @@ -0,0 +1,212 @@ +-- SOURCE: https://www.holistics.io/blog/calculate-cohort-retention-analysis-with-sql/ + +-- IMPORT +WITH companies AS ( + SELECT * FROM {{ ref('dim_shipping__companies') }} +), + +origin_warehouse_shipping_packing_lists AS ( + SELECT * FROM {{ ref('fct_shipping__origin_warehouse_shipping_packing_lists') }} +), + + +-- LOGIC +company_register_month_year AS ( + + SELECT + companies.sub_company_id, + companies.sub_company_marking_id, + companies.sub_company_created_datetime, + + IFF( + MAX(origin_warehouse_shipping_packing_lists.origin_warehouse_shipping_order_created_datetime) IS NULL, + 1, + 0 + ) AS is_never_order_company, + + DATE(DATE_TRUNC( + 'MONTH', + companies.sub_company_created_datetime + )) AS register_month_year, + + DATE(DATE_TRUNC( + 'MONTH', + MIN(origin_warehouse_shipping_packing_lists.origin_warehouse_shipping_order_created_datetime) + )) AS first_order_month_year + + FROM companies + + LEFT JOIN origin_warehouse_shipping_packing_lists + ON (companies.sub_company_id = origin_warehouse_shipping_packing_lists.sub_company_id) + + GROUP BY + companies.sub_company_id, + companies.sub_company_marking_id, + companies.sub_company_created_datetime, + register_month_year + +), + +company_order_count_from_registration_date AS ( + + SELECT + origin_warehouse_shipping_packing_lists.sub_company_id, + + DATEDIFF( + MONTH, + company_register_month_year.sub_company_created_datetime, + origin_warehouse_shipping_packing_lists.origin_warehouse_shipping_order_created_datetime + ) AS order_month + + FROM origin_warehouse_shipping_packing_lists + + LEFT JOIN company_register_month_year + ON (origin_warehouse_shipping_packing_lists.sub_company_id = company_register_month_year.sub_company_id) + + GROUP BY + origin_warehouse_shipping_packing_lists.sub_company_id, + order_month + +), + +company_first_order_from_registration_date AS ( + + SELECT + origin_warehouse_shipping_packing_lists.sub_company_id, + DATE(DATE_TRUNC('MONTH', sub_company_created_datetime)) AS sub_company_created_datetime, + + MIN(DATEDIFF( + MONTH, + company_register_month_year.sub_company_created_datetime, + origin_warehouse_shipping_packing_lists.origin_warehouse_shipping_order_created_datetime + )) AS first_order_month + + FROM origin_warehouse_shipping_packing_lists + + LEFT JOIN company_register_month_year + ON (origin_warehouse_shipping_packing_lists.sub_company_id = company_register_month_year.sub_company_id) + + GROUP BY + origin_warehouse_shipping_packing_lists.sub_company_id, + sub_company_created_datetime + +), + +cohort_size_by_month_year AS ( + + SELECT + register_month_year, + SUM(is_never_order_company) AS count_never_order_company, + COUNT(register_month_year) AS count_total_company + + FROM company_register_month_year + + GROUP BY register_month_year + + ORDER BY register_month_year + +), + +order_retention AS ( + + SELECT + company_register_month_year.register_month_year, + company_order_count_from_registration_date.order_month, + COUNT(company_register_month_year.register_month_year) AS count_retained_company + + FROM company_order_count_from_registration_date + + LEFT JOIN company_register_month_year + ON (company_order_count_from_registration_date.sub_company_id = company_register_month_year.sub_company_id) + + GROUP BY + company_register_month_year.register_month_year, + company_order_count_from_registration_date.order_month + +), + +first_time_order_retention AS ( + + SELECT + sub_company_created_datetime, + first_order_month, + COUNT(first_order_month) AS count_first_order_company + + FROM company_first_order_from_registration_date + + GROUP BY + sub_company_created_datetime, + first_order_month + +), + +cohort_analysis_table AS ( + + SELECT + order_retention.register_month_year, + order_retention.order_month, + order_retention.count_retained_company AS retained_company, + + cohort_size_by_month_year.count_total_company AS total_registered_company, + cohort_size_by_month_year.count_never_order_company, + + first_time_order_retention.count_first_order_company AS count_first_order_company, + + DIV0( + retained_company, + total_registered_company + ) AS retention_rate_overall, + + DIV0( + retained_company, + ( total_registered_company - cohort_size_by_month_year.count_never_order_company ) + ) AS retention_rate_exclude_never_order_company, + + DIV0( + count_first_order_company, + ( total_registered_company - count_never_order_company ) + ) AS first_order_percentage, + + '{{ modules.datetime.datetime.now(modules.pytz.timezone("Asia/Kuala_Lumpur")) }}' AS _dbt_ran_datetime + + FROM order_retention + + LEFT JOIN cohort_size_by_month_year + ON (order_retention.register_month_year = cohort_size_by_month_year.register_month_year) + + LEFT JOIN first_time_order_retention + ON (order_retention.register_month_year = first_time_order_retention.sub_company_created_datetime) + AND (order_retention.order_month = first_time_order_retention.first_order_month) + + ORDER BY + order_retention.register_month_year, + order_retention.order_month + +), + + +-- FINAL +final_rep_shipping__cohort_analysis AS ( + + SELECT + -- dimensions + register_month_year, + total_registered_company, + order_month, + + -- measures + count_never_order_company, + count_first_order_company, + retained_company, + retention_rate_overall, + retention_rate_exclude_never_order_company, + first_order_percentage, + + -- metadata + _dbt_ran_datetime + + FROM cohort_analysis_table + +) + +SELECT * FROM final_rep_shipping__cohort_analysis \ No newline at end of file