私たちのプラットフォームの 1 日の平均ユーザー数を知りたいです。制限は、BigQuery 用の SQL を作成する BI ツール (Looker) にこれを実装する必要があることです。そのため、select ステートメントにカスタム SQL コードを入れることしかできず、任意にクエリを作成することはできません。
少量のデータで機能するソリューションを見つけましたが、それを拡張すると、配列の 100MB のハード リミットでエラーがスローされます。
連結と分割は、配列のサイズを小さくすることです。最初に STRUCT(id, date) を使用しましたが、STRUCT で DISTINCT を使用することはできません。
ファイルサイズの問題は関数内には表示されず、ARRAY_AGG(
CREATE TEMP FUNCTION trend_daily_avg(columns_arr ARRAY<STRING>) AS ((
SELECT AVG(value)
FROM (
SELECT
COUNT(DISTINCT columns_arr.value_column) as value,
FROM (
SELECT
SPLIT(concatstring, " ")[SAFE_OFFSET(1)] as value_column,
SPLIT(concatstring, " ")[SAFE_OFFSET(0)] as time_column,
FROM UNNEST(columns_arr) concatstring
) columns_arr
GROUP BY columns_arr.time_column
)
));
WITH dummy_data as (
SELECT "10-10-2021" as view_date, 0001 as full_visitor_id, "group-1" as hostname UNION ALL
SELECT "10-10-2021" as view_date, 0002 as full_visitor_id, "group-1" as hostname UNION ALL
SELECT "10-10-2021" as view_date, 0001 as full_visitor_id, "group-1" as hostname UNION ALL
SELECT "11-10-2021" as view_date, 0002 as full_visitor_id, "group-2" as hostname UNION ALL
SELECT "11-10-2021" as view_date, 0003 as full_visitor_id, "group-2" as hostname UNION ALL
SELECT "11-10-2021" as view_date, 0001 as full_visitor_id, "group-1" as hostname UNION ALL
SELECT "12-10-2021" as view_date, 0002 as full_visitor_id, "group-2" as hostname UNION ALL
SELECT "12-10-2021" as view_date, 0002 as full_visitor_id, "group-2" as hostname
)
SELECT
hostname,
count(distinct full_visitor_id) as users_dedup,
trend_daily_avg(ARRAY_AGG( DISTINCT
CONCAT(view_date, " ", full_visitor_id) IGNORE NULLS
)) as average_trend, # This works for a small amount of data but not in production
ARRAY_AGG( DISTINCT
CONCAT(view_date, " ", full_visitor_id) IGNORE NULLS
) as average_trend, # This also doesnt work, the upper query fails at this part
FROM ( # Subselect cannot be touched as it cannot be integrated into the BI tool
SELECT
view_date,
full_visitor_id,
hostname, # More dimensions get dynamically added and then grouped
FROM dummy_data
)
GROUP BY hostname;
どうにかして BigQuery の最大行サイズを増やすか、大量の配列を作成する必要がないようにクエリを書き直すことはできますか?
編集:機能する1つの解決策は、毎日(日の粒度の場合)または月(月の粒度の場合)を別々に配列に追加することです。これは間違いなく理想的なソリューションではなく、非常に非効率的ですが、機能します。これをより効率的にする方法はありますか?1 か月の日付と ID だけで約 30 GB のデータがあり、3 年間の範囲で最大 1000 のサブクエリがあるのはかなり悪いことです。
CREATE TEMP FUNCTION avg_array(arr ANY TYPE) AS ((
SELECT
AVG(val)
FROM(
SELECT val
FROM UNNEST(arr) val
where val > 0
)
)
);
select
count(distinct id) as users_dedup,
avg_array([
count(distinct case when day = '2021-01-01' then id else null end),
count(distinct case when day = '2021-02-01' then id else null end),
count(distinct case when day = '2021-03-01' then id else null end),
count(distinct case when day = '2021-04-01' then id else null end),
count(distinct case when day = '2021-05-01' then id else null end),
count(distinct case when day = '2021-06-01' then id else null end),
count(distinct case when day = '2021-07-01' then id else null end),
count(distinct case when day = '2021-08-01' then id else null end),
count(distinct case when day = '2021-09-01' then id else null end),
count(distinct case when day = '2021-10-01' then id else null end),
count(distinct case when day = '2021-11-01' then id else null end),
count(distinct case when day = '2021-12-01' then id else null end)
]) as avg_monthly_users
from (
select '123' as id, '2021-01-01' as day
union all
select '456' as id, '2021-02-01' as day
union all
select '123' as id, '2021-03-01' as day
)