将常规函数与 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 问题的主要内容,如果未能解决你的问题,请参考以下文章