簡體   English   中英

如何根據 BigQuery 中的另一個現有行為每個用戶添加記錄?

[英]How to add records for each user based on another existing row in BigQuery?

在這里發布以防萬一有人擁有更多的知識,可能無法幫助我指明方向。

我有一張這樣的表:

| 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 多個用戶。

我的最終目標是顯示諸如每天平均得分之類的東西。 作為背景,由於我們的邏輯,如果分數不是在特定日期記錄的,這意味着用戶仍在記錄的最后一個分數中,這就是為什么我每天都需要為每個用戶提供分數。

我真的很感激我能得到的任何幫助! 我一直在嘗試不同的選擇但沒有成功

下面是 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     

如果應用於您問題中的樣本數據 - 輸出是

在此處輸入圖片說明

一個選項使用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

我認為最有效的方法是使用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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM