【问题标题】:Get Most Recent Column Value With Nested And Repeated Fields使用嵌套和重复字段获取最新列值
【发布时间】:2016-05-11 02:19:01
【问题描述】:

我有一个结构如下的表:

以及其中的以下数据:

[
  {
    "addresses": [
      {
        "city": "New York"
      },
      {
        "city": "San Francisco"
      }
    ],
    "age": "26.0",
    "name": "Foo Bar",
    "createdAt": "2016-02-01 15:54:25 UTC"
  },
  {
    "addresses": [
      {
        "city": "New York"
      },
      {
        "city": "San Francisco"
      }
    ],
    "age": "26.0",
    "name": "Foo Bar",
    "createdAt": "2016-02-01 15:54:16 UTC"
  }
]

我想做的是重新创建相同的表(相同的结构),但只有最新版本的行。在此示例中,假设我想按名称对所有内容进行分组,并获取最近 createdAt 所在的行。 我试图做这样的事情:Google Big Query SQL - Get Most Recent Column Value 但我无法让它与记录和重复字段一起使用。

【问题讨论】:

  • 您当然知道 - 所以只是提醒一下 - 重要的是 SO - 您可以使用已发布答案左侧投票下方的勾号 mark accepted answer。请参阅meta.stackexchange.com/questions/5234/… 了解为什么它很重要!好的做法是vote on answer。投票选出有帮助的答案。还有更多...您可以查看当有人回答您的问题时该怎么做 - stackoverflow.com/help/someone-answers

标签: sql google-bigquery


【解决方案1】:

我真的希望 Google 团队的某个人能就这个问题提供答案,因为这是在 SO 上非常常见的主题/问题。 BigQuery 绝对不够友好,无法将嵌套/重复的内容从 BQ 查询写回 BQ。

所以,我将提供我很久以前找到的解决方法。我不喜欢它,但是(这就是我希望 Google 团队给出答案的原因)它有效。我希望您能够为您的特定场景采用它

因此,根据您的示例,假设您有如下表格

并且您希望根据 createdAt 列获取最新记录,因此结果将如下所示:

下面的代码是这样做的:

SELECT name, age, createdAt, addresses.city
FROM JS( 
  ( // input table 
    SELECT name, age, createdAt, NEST(city) AS addresses 
    FROM (
      SELECT name, age, createdAt, addresses.city 
      FROM (
        SELECT 
          name, age, createdAt, addresses.city, 
          MAX(createdAt) OVER(PARTITION BY name, age) AS lastAt
        FROM yourTable
      )
      WHERE createdAt = lastAt
    )
    GROUP BY name, age, createdAt
  ), 
  name, age, createdAt, addresses, // input columns 
  "[ // output schema 
    {'name': 'name', 'type': 'STRING'},
    {'name': 'age', 'type': 'INTEGER'},
    {'name': 'createdAt', 'type': 'INTEGER'},
    {'name': 'addresses', 'type': 'RECORD',
     'mode': 'REPEATED',
     'fields': [
       {'name': 'city', 'type': 'STRING'}
       ]    
     }
  ]", 
  "function(row, emit) { // function 
    var c = []; 
    for (var i = 0; i < row.addresses.length; i++) { 
      c.push({city:row.addresses[i]});
    }; 
    emit({name: row.name, age: row.age, createdAt: row.createdAt, addresses: c}); 
  }"
) 

上述代码的工作方式是:它隐式地展平原始记录;查找属于最近记录的行(按名称和年龄划分);将这些行组合回各自的记录中。最后一步是使用JS UDF 进行处理以构建正确的架构,该架构实际上可以作为嵌套/重复与扁平化写回 BigQuery 表

最后一步是此解决方法中最烦人的部分,因为每次都需要针对特定​​架构进行自定义

请注意,在此示例中 - 它只是地址记录中的一个嵌套字段,因此 NEST() 函数有效。在你有不止一个的场景中 内部字段 - 上述方法仍然有效,但您需要将这些字段连接起来以将它们放入 nest() 中,而不是在 js 函数中进行额外的拆分这些字段等。
您可以在以下答案中看到示例:
Create a table with Record type column
create a table with a column type RECORD
How to store the result of query on the current table without changing the table schema?

我希望这是您尝试并让您的案例发挥作用的良好基础!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-04
    • 2021-09-19
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 2021-01-03
    • 2019-09-12
    相关资源
    最近更新 更多