Big Query ROW_NUMBER()根据嵌套的位置中断查询

时间:2016-03-13 03:03:56

标签: sql google-bigquery window-functions row-number

我在BQ中运行了一组相当复杂的嵌套聚合,并遇到了以下问题:

如果我在查询的最高级别请求ROW_NUMBER(),BQ似乎无法识别我的列名。如果我在查询的最里面请求ROW_NUMBER(),我会神奇地得到一个行号。

这是我查询的(简化)版本:

SELECT
  ROW_NUMBER() OVER() row_id, // query fails with ROW_NUMBER() here
  price,
  store,
  week,
  f.product product,
  COUNT(DISTINCT f.product) OVER (PARTITION BY store, week) product_count,
  price_max-price_min weekly_price_range,
FROM (
  SELECT
    MIN(price) OVER (PARTITION BY store, week) price_min,
    MAX(price) OVER (PARTITION BY store, week) price_max,
    *
  FROM (
    SELECT
      dollars / units price,
      *
    FROM store_sales_facts f
    JOIN product_facts p
    ON p.product = f.product 
  )
)

如果我删除了对ROW_NUMBER()的请求,查询会成功。如果我包含ROW_NUMBER()函数,则BQ会失败并显示"错误:字段'价格'找不到"

我使用以下方法作为解决方法,但我很好奇是否有人可以解释为什么这有效,而上述情况并非如此?

SELECT
  row_id,
  price,
  store,
  week,
  f.product product,
  COUNT(DISTINCT f.product) OVER (PARTITION BY store, week) product_count,
  price_max-price_min weekly_price_range,
FROM (
  SELECT
    MIN(price) OVER (PARTITION BY store, week) price_min,
    MAX(price) OVER (PARTITION BY store, week) price_max,
    *
  FROM (
    SELECT
    ROW_NUMBER() OVER() row_id, // query succeeds with ROW_NUMBER() here
      dollars / units price,
      *
    FROM store_sales_facts f
    JOIN product_facts p
    ON p.product = f.product 
  )
)
ORDER BY row_id

我理解ROW_NUMBER()窗口函数最近才被添加。这是函数本身的怪癖吗?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

假设“我们看到的是您正在执行的内容”,那么我建议核心问题可能是缺少对列的表引用。事实和维度表共享至少一个列名(产品),因此您可能会有歧义。因此,我建议的第二件事是对表进行别名并使用别名和每个列引用,但这当然是在第一次建议之后发生的,即使用显式列名替换 if (activity.Type == ActivityTypes.Message) { var connector = new ConnectorClient(new Uri(activity.ServiceUrl)); Activity isTypingReply = activity.CreateReply(); isTypingReply.Type = ActivityTypes.Typing; await connector.Conversations.ReplyToActivityAsync(isTypingReply); await Conversation.SendAsync(activity, () => new RootDialog()); } (与相关的表别名)。

select *

row_number()的具体问题我无法复制甚至测试,但在前一个问题RANK or ROW_NUMBER in BigQuery over a large dataset,似乎对该函数的可伸缩性存在一些疑问。我建议你可能需要考虑一些分区,或者完全避免分区,因为我不知道它会给你带来什么价值。如果你对每一行都有一些独特的引用,那么使用事实表(f.id I presume)的已经唯一的行引用形式会更有效。

SELECT ROW_NUMBER() OVER () row_id , d.price , d.store , d.WEEK , d.product , COUNT(DISTINCT d.product) OVER (PARTITION BY d.store, d.WEEK) product_count , d.price_max - d.price_min weekly_price_range FROM ( SELECT MIN(p.price) OVER (PARTITION BY store, WEEK) price_min , MAX(p.price) OVER (PARTITION BY store, WEEK) price_max , p.product, p.store, p.week FROM ( SELECT f.dollars / f.units price , f.product , s.store , f.WEEK FROM store_sales_facts f JOIN product_facts p ON p.product = f.product ) p ) d 的另一个长期可能性是,即使您并不真正关心结果行编号的顺序,over子句也可能需要按参数排序。此问题存在于某些其他dbs中,并通过对常量(例如“select null”或“select 1”)进行排序来解决,例如

row_number() over()

但是我没有证据表明BigQuery中存在此问题,或者通过该解决方法解决了这个问题。