【问题标题】:How to query a denormalized BigQuery table to output nested and repeated fields如何查询非规范化 BigQuery 表以输出嵌套和重复的字段
【发布时间】:2019-05-10 02:42:20
【问题描述】:

我有一些数据定期加载到 BigQuery 数据库中。每一行代表作为履行订单的一部分的一件库存的移动。

相关订单和“order_product”信息作为嵌套记录嵌入在行中。

以下是一些行的示例:

|----------|----------|----------|------------------|------------------------|---------------------|---------------------------------|
| move_id  | quantity | order.id | order_product.id | order_product.quantity | order_product.price |      item_reference_number      |
|----------|----------|----------|------------------|------------------------|---------------------|---------------------------------|
|    1     |    1     |     1    |         1        |            1           |           5         |               ABC               |
|----------|----------|----------|------------------|------------------------|---------------------|---------------------------------|
|    2     |    1     |     1    |         2        |            1           |           7         |               DEF               |
|----------|----------|----------|------------------|------------------------|---------------------|---------------------------------|
|    3     |    1     |     1    |         2        |            1           |           7         |               XYZ               |
|----------|----------|----------|------------------|------------------------|---------------------|---------------------------------|

如您所见,该表显示了三个股票走势。都与订单 1 相关。

Order 1 由一个 order_product 1 和一个 order_product 2 组成。Order_product 1 由一个库存移动组成,move_id 1 用于项目 ABC。

Order_product 2 包含两个库存变动,move_id 2 用于商品 DEF,move_id 3 用于商品 XYZ。

如何编写查询以将此数据转换为具有适当嵌套/重复字段的表?换句话说,我希望数据看起来像这样:

|-----------|------------------|------------------------|---------------------|------------------------|---------------------|----------------------------------|
| order_id  | order_product.id | order_product.quantity | order_product.price |      stock_move.id     | stock_move.quantity | stock_move.item_reference_number |
|-----------|------------------|------------------------|---------------------|------------------------|---------------------|----------------------------------|
|     1     |         1        |            1           |          5          |            1           |           1         |                ABC               |
|           |------------------|------------------------|---------------------|------------------------|---------------------|----------------------------------|
|           |         2        |            1           |          7          |            2           |           1         |                DEF               |
|           |                  |                        |                     |------------------------|---------------------|----------------------------------|
|           |                  |                        |                     |            3           |           1         |                XYZ               |
|-----------|------------------|------------------------|---------------------|------------------------|---------------------|----------------------------------|

我一直在阅读this post,这似乎表明ARRAY_AGG 可能是我需要的,但我不知道如何正确使用它来解决我的问题。

我认为我的问题是我正在努力将嵌套的 order_products 减少到每一行,同时为每个 order_product 填充正确的嵌套/重复库存移动。

甚至可以按照我的要求做吗?我非常感谢任何帮助我指出正确的方向。

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    以下是 BigQuery 标准 SQL

    #standardSQL
    SELECT order_id,
      ARRAY_AGG(product ORDER BY product.id) order_product,
      ARRAY_CONCAT_AGG(stock_move) stock_move
    FROM (
      SELECT order_id, 
        STRUCT(order_product.id, order_product.quantity, order_product.price) product,
        ARRAY_AGG(STRUCT(move_id AS id, quantity AS quantity, item_reference_number AS item_reference_number)) stock_move
      FROM `project.dataset.table`
      GROUP BY order_id, order_product.id, order_product.quantity, order_product.price
      ORDER BY order_product.id -- <-- this is to make sure stock_move array is ordered as in your expected output  - but really not needed here
    )
    GROUP BY order_id
    

    当应用于您的示例数据时 - 上面会产生如下结果

    我不确定这是否正是你的意思,因为你的例子仍然有点模棱两可,但希望这能给你一个想法

    另外请注意:我假设您的示例中的 order.id 实际上是 order_id 否则它没有多大意义,但我可能对此有误(正如我提到的那样,您的示例仍然“有点”模棱两可)

    【讨论】:

    • 感谢您的回复。它应该是order.id。订单是行的嵌套资源。实际上,我想保留订单上的其他字段,例如order.source,但为了简化示例,我没有显示它们。这有什么改变吗?另外,有什么方法可以解释查询的不同部分正在做什么?我是新手,想了解每件作品的原因。
    • 您说ORDER BY order_product.id 实际上没有必要是什么意思?我发现没有它,库存变动与正确的订单产品无关,但我很困惑为什么会这样。我认为我缺少有关嵌套字段的一些基本知识。这些库存变动不是嵌套在他们的 order_product 行中吗?那么他们不应该自动留在 order_product 行的任何地方吗?
    • 刮掉这个额外的评论 - 我应该在发布答案时删除这个。显然没有命令它不会产生预期的结果,这就是我在那里拥有它的原因
    • 感谢您的回复。但这对我来说并不明显。为什么需要 ORDER BY?那些库存移动行不是嵌套在它们的父 order_products 中吗?此外,外部查询 ARRAY_AGG 函数中是否需要 ORDER BY ?那个好像没什么区别。
    • 正如我所提到的-您问题中的示例模棱两可,尚不清楚您的期望。所以我试图尽可能接近你的预期结果(甚至是视觉上)所以这就是为什么我添加了 order 以便它按产品顺序输出
    【解决方案2】:

    以下 SQL 会满足您的期望吗?

    我以 order_product 方式创建了 stock_move。

    WITH original_table AS (
        SELECT 1 AS move_id, 1 AS quantity, STRUCT(1 AS id) AS `order`, STRUCT(1 AS id, 1 AS quantity, 5 AS price) AS order_product, "ABC" AS item_reference_number
        UNION ALL
        SELECT 2 AS move_id, 1 AS quantity, STRUCT(1 AS id) AS `order`, STRUCT(2 AS id, 1 AS quantity, 7 AS price) AS order_product, "DEF" AS item_reference_number
        UNION ALL
        SELECT 3 AS move_id, 1 AS quantity, STRUCT(1 AS id) AS `order`, STRUCT(2 AS id, 1 AS quantity, 7 AS price) AS order_product, "XYZ" AS item_reference_number
    ),
    
    t1 AS (
        SELECT DISTINCT
            move_id,
            quantity,
            `order`.id AS order_id,
            order_product.id AS order_product_id,
            order_product.quantity AS order_product_quantity,
            order_product.price AS order_product_price,
            item_reference_number
        FROM original_table
    ),
    
    t2 AS (
        SELECT
            order_id,
            order_product_id,
            order_product_quantity,
            order_product_price,
            ARRAY_AGG(STRUCT(move_id, quantity, item_reference_number) ORDER BY move_id) AS stock_move
        FROM t1
        GROUP BY order_id, order_product_id, order_product_quantity, order_product_price
    ),
    
    t3 AS (
        SELECT
            order_id,
            ARRAY_AGG(STRUCT(order_product_id AS id, order_product_quantity AS quantity, order_product_price AS price, stock_move) ORDER BY order_product_id) AS order_product
        FROM t2
        GROUP BY order_id
    )
    
    SELECT * FROM t3
    
    |-----------|------------------|------------------------|---------------------|----------------------------------|-----------------------------------|------------------------------------------------|
    | order_id  | order_product.id | order_product.quantity | order_product.price | order_product.stock_move.move_id | order_product.stock_move.quantity | order_product.stock_move.item_reference_number |
    |-----------|------------------|------------------------|---------------------|----------------------------------|-----------------------------------|------------------------------------------------|
    |     1     |         1        |            1           |          5          |              1                   |           1                       |                ABC                             |
    |           |------------------|------------------------|---------------------|----------------------------------|-----------------------------------|------------------------------------------------|
    |           |         2        |            1           |          7          |              2                   |           1                       |                DEF                             |
    |           |                  |                        |                     |----------------------------------|-----------------------------------|------------------------------------------------|
    |           |                  |                        |                     |              3                   |           1                       |                XYZ                             |
    |-----------|------------------|------------------------|---------------------|----------------------------------|-----------------------------------|------------------------------------------------|
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-17
      • 1970-01-01
      • 2013-02-15
      • 2016-06-09
      • 2017-12-23
      • 1970-01-01
      • 1970-01-01
      • 2017-09-25
      相关资源
      最近更新 更多