将常规函数与 WINDOW 函数结合使用的 Google BigQuery SQL 问题

Posted

技术标签:

【中文标题】将常规函数与 WINDOW 函数结合使用的 Google BigQuery SQL 问题【英文标题】:Google BigQuery SQL issue with combining regular functions with WINDOW functions 【发布时间】:2019-11-18 17:57:48 【问题描述】:

我正在查看电子商务网站的订单表,并尝试构建一个包含每个客户的一些基本信息的客户表。

我在尝试将 NTH_VALUE 之类的 WINDOW 函数与普通函数结合使用时遇到了问题。

订单表如下所示:

order_id | customer_id | order_date | revenue
----------------------------------------------
    1    |      11     | 2017-01-01 |  5.0
    2    |      11     | 2018-02-01 |  2.25
    3    |      12     | 2019-03-01 |  1.0
    4    |      13     | 2016-04-01 |  12.0
    5    |      13     | 2016-05-01 |  15.25
    6    |      13     | 2018-06-01 |  25.25

我希望构建一个如下所示的客户表:

customer_id | num_orders | first_order_date | first_order_revenue | second_order_date
--------------------------------------------------------------------------------------
      11    |     2      |    2017-01-01    |        5.0          |    2018-02-01
      12    |     1      |    2019-03-01    |        1.0          |        n/a
      13    |     3      |    2016-04-01    |        12.0         |    2018-06-01

我的代码应该是这样的:

SELECT
customer_id,
COUNT(customer_id) num_orders,
MIN(order_date) first_order_date,
FIRST_VALUE(revenue) OVER w1 first_order_revenue,
NTH_VALUE(order_date, 2) OVER w1 second_order_date

FROM `orders`
GROUP BY customer_id
WINDOW w1 as (PARTITION BY customer_id ORDER BY order_date ASC)

但它告诉我需要通过以下错误对“收入”和“订单日期”进行分组:

“SELECT 列表表达式引用在 [5:13] 时既未分组也未汇总的列收入”

但是当我这样做时,它会为每个订单返回一行,其中 first_order_date 对于每个订单都不同,first_order_revenue 对于每个订单都是相同的(正确)值,并且 second_order_date 是正确的,除了第一行......它在哪里空:

customer_id | num_orders | first_order_date | first_order_revenue | second_order_date
--------------------------------------------------------------------------------------
      13    |      1     |    2016-04-01    |        12.0         |       *null*
      13    |      1     |    2016-05-01    |        12.0         |     2016-05-01
      13    |      1     |    2018-06-01    |        12.0         |     2016-05-01

我正在慢慢地自学 SQL,但是我在网上找不到任何解决方案。我猜它可能需要一个嵌套的 SELECT 语句用于 WINDOW 函数,然后与非 WINDOW 函数连接?类似的东西?我尝试了几种不同的解决方案,但到目前为止都没有任何效果。

感谢任何可以提供帮助的人!

【问题讨论】:

【参考方案1】:

我认为子查询和条件聚合可能更简单:

SELECT customer_id, COUNT(*) num_orders,
       MIN(order_date) first_order_date,
       MAX(CASE WHEN seqnum = 1 THEN revenue END) as revenue_1,
       MAX(CASE WHEN seqnum = 2 THEN revenue END) as revenue_2
FROM (SELECT o.*,
             ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) as seqnum
      FROM `orders` o
     ) o
GROUP BY customer_id;

或者,将值放入数组中:

SELECT customer_id, COUNT(*) num_orders,
       MIN(order_date) first_order_date,
       ARRAY_AGG(revenue ORDER BY order_date LIMIT 2) as revenue_1_2
FROM `orders` o
GROUP BY customer_id;

【讨论】:

啊有趣。使用 ROW_NUMBER() 创建 'seqnum' 列,然后如果它与您想要的 seqnum 匹配,您就可以拉出您想要的任何列。 糟糕,它发送得太早了。打算补充一下:使用 MAX 只是一种解决方法,无需对它们进行 GROUP 即可提取这些值,对吗? @LeeLK 。 . .是的。 MAX() 为每个 seqnum 提取一个值,并且只有一个值。

以上是关于将常规函数与 WINDOW 函数结合使用的 Google BigQuery SQL 问题的主要内容,如果未能解决你的问题,请参考以下文章

将分析函数与汇总相结合

PostgreSQL窗口函数(转)

窗口事件上的JQuery函数:结合加载和调整大小[重复]

JavaScript函数与Window对象

将连接与其他连接或常规查询相结合

将 BigQuery SQL 与内置 Python 函数结合使用