如何根据 BigQuery 中的另一个现有行为每个用户添加记录?
Posted
技术标签:
【中文标题】如何根据 BigQuery 中的另一个现有行为每个用户添加记录?【英文标题】:How to add records for each user based on another existing row in BigQuery? 【发布时间】:2020-11-23 19:54:41 【问题描述】:在这里发帖,以防有更多知识的人可以帮助我找到一些方向。
我有一张这样的桌子:
| Row | date |user id | score |
-----------------------------------
| 1 | 20201120 | 1 | 26 |
-----------------------------------
| 2 | 20201121 | 1 | 14 |
-----------------------------------
| 3 | 20201125 | 1 | 0 |
-----------------------------------
| 4 | 20201114 | 2 | 32 |
-----------------------------------
| 5 | 20201116 | 2 | 0 |
-----------------------------------
| 6 | 20201120 | 2 | 23 |
-----------------------------------
但是,据此,我需要为每个用户记录每一天,如果用户缺少一天,那么应该保留最后记录的分数,那么我会得到这样的结果:
| Row | date |user id | score |
-----------------------------------
| 1 | 20201120 | 1 | 26 |
-----------------------------------
| 2 | 20201121 | 1 | 14 |
-----------------------------------
| 3 | 20201122 | 1 | 14 |
-----------------------------------
| 4 | 20201123 | 1 | 14 |
-----------------------------------
| 5 | 20201124 | 1 | 14 |
-----------------------------------
| 6 | 20201125 | 1 | 0 |
-----------------------------------
| 7 | 20201114 | 2 | 32 |
-----------------------------------
| 8 | 20201115 | 2 | 32 |
-----------------------------------
| 9 | 20201116 | 2 | 0 |
-----------------------------------
| 10 | 20201117 | 2 | 0 |
-----------------------------------
| 11 | 20201118 | 2 | 0 |
-----------------------------------
| 12 | 20201119 | 2 | 0 |
-----------------------------------
| 13 | 20201120 | 2 | 23 |
-----------------------------------
我正在尝试使用 StandardSQL 在 BigQuery 中完成此操作。我知道如何在以下空日期中保持相同的分数,但我真的不知道如何为每个用户的缺失日期添加新行。另外,请记住,这个例子只有 2 个用户,但在我的数据中我有超过 1500 个。
我的最终目标是显示每天的平均得分。作为背景,由于我们的逻辑,如果分数不是在特定日期记录的,这意味着用户仍然在最后记录的分数中,这就是为什么我需要每天为每个用户记录一个分数。
如果能得到任何帮助,我将不胜感激!我一直在尝试不同的选择,但没有成功
【问题讨论】:
有一个日历帮助表/cte。外连接。 我如何为每个用户添加它?我已经这样做了,但是我不知道如何确保我为每个用户添加丢失的日期不只是一次 【参考方案1】:以下是 BigQuery 标准 SQL
#standardSQL
select date, user_id,
last_value(score ignore nulls) over(partition by user_id order by date) as score
from (
select user_id, format_date('%Y%m%d', day) date,
from (
select user_id, min(parse_date('%Y%m%d', date)) min_date, max(parse_date('%Y%m%d', date)) max_date
from `project.dataset.table`
group by user_id
) a, unnest(generate_date_array(min_date, max_date)) day
)
left join `project.dataset.table` b
using(date, user_id)
-- order by user_id, date
如果应用于您问题的样本数据 - 输出是
【讨论】:
【参考方案2】:一个选项使用generate_date_array()
创建每个用户的一系列日期,然后使用left join
带来表格。
select d.date, d.user_id,
last_value(t.score ignore nulls) over(partition by d.user_id order by d.date) as score
from (
select t.user_id, d.date
from mytable t
cross join unnest(generate_date_array(min(date), max(date), interval 1 day)) d(date)
group by t.user_id
) d
left join mytable t on t.user_id = d.user_id and t.date = d.date
【讨论】:
【参考方案3】:我认为最有效的方法是使用generate_date_array()
,但方式非常特殊:
with t as (
select t.*,
date_add(lead(date) over (partition by user_id order by date), interval -1 day) as next_date
from t
)
select row_number() over (order by t.user_id, dte) as id,
t.user_id, dte, t.score
from t cross join join
unnest(generate_date_array(date,
coalesce(next_date, date)
interval 1 day
)
) dte;
【讨论】:
以上是关于如何根据 BigQuery 中的另一个现有行为每个用户添加记录?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 bigquery 中的另一个表中获取短语列表的表字段中的匹配计数?
如何在 SQL Bigquery 中的另一个事件之前计算特定事件的数量?
如果一个数组包含使用 BigQuery 的另一个数组的所有值,我如何过滤行?