【问题标题】:Google Big Query SQL - Get Most Recent Column ValueGoogle Bigquery SQL - 获取最新的列值
【发布时间】:2014-10-05 19:46:39
【问题描述】:

我有一个 Google 大查询表,其中有一个 email 列。基本上,每一行都显示了具有该电子邮件地址的用户所在的状态。我想要做的是查询表以获取显示每个电子邮件地址的最新行的结果。我已经尝试了各种GROUP BY's、JOINing 表反对自己以及我将在 MySQL 中使用的通常有趣的东西,但如果整行不匹配,我会不断收到重复的电子邮件。

非常感谢任何帮助!

样本数据

user_email     | user_first_name | user_last_name | time      | is_deleted
test@test.com  | Joe             | John           | 123456790 |  1
test@test.com  | Joe             | John           | 123456789 |  0
test2@test.com | Jill            | John           | 123456789 |  0

因此,如果对我想要返回的数据进行采样:

user_email     | user_first_name | user_last_name | time      | is_deleted
test@test.com  | Joe             | John           | 123456790 |  1
test2@test.com | Jill            | John           | 123456789 |  0

【问题讨论】:

    标签: sql google-bigquery


    【解决方案1】:
    SELECT user_email, user_first_name, user_last_name, time, is_deleted 
    FROM (
     SELECT user_email, user_first_name, user_last_name, time, is_deleted
          , RANK() OVER(PARTITION BY user_email ORDER BY time DESC) rank
     FROM table
    )
    WHERE rank=1
    

    【讨论】:

    • 如果您的表格包含嵌套和重复的字段,您将如何做同样的事情?
    • 如果你能提供一个包含嵌套和重复字段的示例表,我会尽力提供答案。请也开始一个新问题!
    • 好的,我创建了一个新问题,您可以在这里找到:stackoverflow.com/questions/35150732/…
    【解决方案2】:

    解决了!

    SELECT l.* FROM [mytable.list] l JOIN (
        SELECT user_email, MAX(time) as time FROM [mytable.list] GROUP EACH BY user_email
    ) j ON j.user_email = l.user_email WHERE j.time = l.time;
    

    【讨论】:

    • 好!也看看使用 OVER() 函数,看看替代答案。
    • 谢谢@FelipeHoffa,使用您的解决方案有什么好处和/或对比?
    • @FelipeHoffa 我同意,请在您的解决方案中添加一些解释。
    【解决方案3】:

    在我的工作中,我发现了使用RANK() 替代(可能是最近的?https://cloud.google.com/bigquery/docs/reference/standard-sql/numbering_functions)替代编号函数ROW_NUMBER() 的潜在缺点。

    with minimal_reproducible as (
    select 'test@test.com' as user_email, 'Joe' as user_first_name, 'John' as user_last_name, 123456790 as time, 1 is_deleted
    union all
    select 'test@test.com', 'Joe', 'John', 123456789, 0
    union all
    select 'test2@test.com', 'Jill', 'John', 123456789, 0
    )
    
    select user_email, user_first_name, user_last_name, time, is_deleted from (
        select *, 
        rank() over (partition by user_email order by time desc) as rank
        from minimal_reproducible) inner_table 
    where rank = 1
    
    

    接受的答案确实提供了所需的解决方案,除非在 order by 子句中的平局事件再次返回重复记录:

    with minimal_reproducible as (
    select 'test@test.com' as user_email, 'Joe' as user_first_name, 'John' as user_last_name, 123456789 as time, 1 is_deleted
    union all
    select 'test@test.com', 'Joe', 'John', 123456789, 0
    union all
    select 'test2@test.com', 'Jill', 'John', 123456789, 0
    )
    
    select user_email, user_first_name, user_last_name, time, is_deleted from (
        select *, 
        rank() over (partition by user_email order by time desc) as rank
        from minimal_reproducible) inner_table 
    where rank = 1;
    

    因此,更好的解决方案是使用ROW_NUMBER() 代替RANK() 以确保(尽管是任意的)唯一的user_email 可能发生的情况:

    with minimal_reproducible as (
    select 'test@test.com' as user_email, 'Joe' as user_first_name, 'John' as user_last_name, 123456789 as time, 1 is_deleted
    union all
    select 'test@test.com', 'Joe', 'John', 123456789, 0
    union all
    select 'test2@test.com', 'Jill', 'John', 123456789, 0
    )
    
    select user_email, user_first_name, user_last_name, time, is_deleted from (
        select *, 
        row_number() over (partition by user_email order by time desc) as row_number
        from minimal_reproducible) inner_table 
    where row_number = 1;
    

    我希望这对任何使用这种方法对表进行重复数据删除的人有所帮助。

    【讨论】:

      猜你喜欢
      • 2019-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多