BigQuery 的 运行 个具有动态日期范围的不同值

BigQuery for running count of distinct values with a dynamic date-range

我们正在尝试进行查询,获取特定年月的唯一客户总和 + 特定日期前 364 天的唯一客户总和。

例如:

我们的客户-table是这样的:

| order_date   | customer_unique_id |
| --------     | --------------     |
| 2020-01-01   | tom@email.com      |
| 2020-01-01   | daisy@email.com    |
| 2019-05-02   | tom@email.com      |

在此示例中,我们有两位客户在 2020 年 1 月 1 日订购,其中一位已经在 364 天的时间范围内订购。

所需的 table 应如下所示:

| year_month | unique_customers |
| --------   | --------------   |
| 2020-01    | 2                |

我们尝试了多种解决方案,例如分区和 windows,但似乎都无法正常工作。棘手的部分是唯一性。我们想要回顾 364 天,但希望根据整个时期而不是根据 date/year/month 对客户进行不同的计数,因为那样我们会得到重复项。例如,如果您按日期、年份或月份进行分区,tom@email.com 将被计算两次而不是一次。

此查询的目标是深入了解 12 个月内一段时间内的订单频率(订单除以客户)。

我们使用 Google BigQuery。

希望有人能帮助我们! :)

这里有一种方法可以达到您想要的结果。请注意,此查询 year-month 加入一个单独的查询,并将其与滚动 364-day-interval 查询加入。

with year_month_distincts as (
    select  
        concat(
           cast(extract(year from order_date) as string), 
           '-', 
           cast(extract(month from order_date) as string)
        ) as year_month,
        count(distinct customer_id) as ym_distincts
    from customer_table
    group by 1
)

select x.order_date, x.ytd_distincts, y.ym_distincts from (
    select 
       a. order_date,
       (select 
           count(distinct customer_id) 
        from customer_table b 
        where b.order_date between date_sub(a.order_date, interval 364 day) and a.order_date 
       ) as ytd_distincts 
    from orders a
    group by 1
) x
join year_month_distincts y on concat(
   cast(extract(year from x.order_date) as string), 
   '-', 
   cast(extract(month from x.order_date) as string)
) = y.year_month

两个可能有用的数组选项。

  1. 按要求回顾 364 天
  2. 如果您想回顾 11 个月(假设报告是每月一次)
month_array AS (
  SELECT 
   DATE_TRUNC(order_date,month) AS order_month,
  STRING_AGG(DISTINCT customer_unique_id) AS cust_mth
  FROM customer_table
  GROUP BY 1
), 

year_array AS (
  SELECT
    order_month, 
   STRING_AGG(cust_mth) OVER(ORDER by UNIX_DATE(order_month) RANGE BETWEEN 364 PRECEDING AND CURRENT ROW) cust_12m
-- (option 2) STRING_AGG(cust_mth) OVER (ORDER by cast(format_date('%Y%m', order_month) as int64) RANGE BETWEEN 99 PRECEDING AND CURRENT ROW) AS cust_12m
FROM month_array
)

SELECT format_date('%Y-%m',order_month) year_month,  
  (SELECT COUNT(DISTINCT cust_unique_id) FROM UNNEST(SPLIT(cust_12m)) AS cust_unique_id) as unique_12m
FROM year_array