从旧版 SQL 迁移:使用标准 SQL 的“WITHIN RECORD”选项

Posted

技术标签:

【中文标题】从旧版 SQL 迁移:使用标准 SQL 的“WITHIN RECORD”选项【英文标题】:Migrating from Legacy SQL: options for "WITHIN RECORD" with Standard SQL 【发布时间】:2017-10-10 18:04:45 【问题描述】:

我正在尝试从 BigQuery Legacy SQL 迁移到标准 SQL。 Legacy 产品提供了查询“WITHIN RECORD”的功能,这在很多场合都派上用场。

我正在寻找一种有效的替代方案,以替代 WITHIN RECORD。我总是可以只使用一些子查询并加入它们,但想知道使用 ARRAY + ORDINAL 是否有更有效的方法。

示例:考虑以下标准 SQL

WITH
  sessPageVideoPlays AS (
    SELECT fullVisitorId, visitNumber, h.page.pagePath,
        # This would previously use WITHIN RECORD in Legacy SQL:
        ARRAY( SELECT eventInfo.eventAction FROM UNNEST(hits)
               WHERE eventInfo.eventCategory="videoPlay" 
               ORDER BY hitNumber DESC
        )[ORDINAL(1)] AS lastVideoSeen
    FROM
          `proj.ga_sessions`, UNNEST(hits) as h
    GROUP BY fullVisitorId, visitNumber, h.page.pagePath, lastVideoSeen
  )
SELECT 
  pagePath, lastVideoSeen, numOccur  
FROM 
     (SELECT    
        pagePath, lastVideoSeen, count(1) numOccur
      FROM
        sessPageVideoPlays
      GROUP BY
        pagePath, lastVideoSeen
)

结果输出:

问题:

1) 我想查看给定页面上的最后一个视频播放事件,这是我使用 WITHIN RECORD 完成的,但我正在尝试上面显示的 ARRAY + ORDINAL 方法。但是,为了使它起作用,我认为 ARRAY() 中的 SELECT 语句必须与外部记录同步,因为它现在被展平了?那准确吗?

2) 我还想获得在给定页面上播放的 COUNT 个 DISTINCT 视频,并想知道是否更有效的方法是加入单独的查询或插入另一个内联聚合函数,就像上面的 ARRAY 一样。

任何建议将不胜感激。

【问题讨论】:

【参考方案1】:

1) 我想查看给定页面上的最后一个视频播放事件, 这是我使用 WITHIN RECORD 完成的,但我正在尝试 上面显示的 ARRAY + ORDINAL 方法。然而,为了这个工作, 我在想 ARRAY() 中的 SELECT 语句必须同步 到外部记录,因为它现在被压平了?准确吗?

我认为这是正确的。通过您的查询,内部查询中的 UNNEST(hits) 将独立于外部 UNNEST,并且可能不是您想要的。

我想也许一种写法是这样的:

WITH
  sessPageVideoPlays AS (
    SELECT fullVisitorId, visitNumber,
        ARRAY(
          SELECT AS STRUCT pagePath, lastVideoSeen FROM (
            SELECT
              page.pagePath,
              eventInfo.eventAction AS lastVideoSeen,
              ROW_NUMBER() OVER (PARTITION BY page.pagePath ORDER BY hitNumber DESC) AS rank
            FROM UNNEST(hits)
            WHERE eventInfo.eventCategory="videoPlay")
          WHERE rank = 1
        ) AS lastVideoSeenOnPage
    FROM
      `proj.ga_sessions`
  )
SELECT 
  pagePath, lastVideoSeen, numOccur  
FROM (
  SELECT
    pagePath, lastVideoSeen, count(1) numOccur
  FROM
    sessPageVideoPlays, UNNEST(lastVideoSeenOnPage)
  GROUP BY
    pagePath, lastVideoSeen
)

2) 我还想在给定的设备上播放 COUNT 个 DISTINCT 视频 页面并想知道是否会加入更有效的方法 单独的查询或插入另一个内联聚合函数,例如 用上面的 ARRAY 完成。

我认为两者都可以,但是插入另一个内联聚合函数会使它们更接近地评估它们,因此如果有机会,查询引擎可能会更容易优化。

【讨论】:

非常感谢 Nhan,您在 Rank 分区上使用 Row_Number 的方法效果很好!

以上是关于从旧版 SQL 迁移:使用标准 SQL 的“WITHIN RECORD”选项的主要内容,如果未能解决你的问题,请参考以下文章

旧版 VB6 应用程序访问 SQL 数据库迁移

bigquery - 自定义字段上的分区 - 仅适用于标准 SQL?

BigQuery 中用于 Google Analytics 数据的标准 SQL 还是旧版 SQL?

将旧版 SQL 查询转换为标准 SQL

在 BigQuery 中使用 dryRun 区分标准和旧版 SQL 查询的替代方法?

sql 作者:Matt B,2016-10-17:帮助用户将101个Facebook导入时间表从旧的Facebook Importer插件迁移到