在我的PostgreSQL 14.8数据库中,我有一个名为orders
的表,如下所示:
CREATE TABLE orders (
user_id int
, order_id int
, order_date date
, quantity int
, revenue float
, product text
);
INSERT INTO orders VALUES
(1, 1, '2021-03-05', 1, 15, 'books'),
(1, 2, '2022-03-07', 1, 3, 'music'),
(1, 3, '2022-06-15', 1, 900, 'travel'),
(1, 4, '2021-11-17', 2, 25, 'books'),
(2, 5, '2022-08-03', 2, 32, 'books'),
(2, 6, '2021-04-12', 2, 4, 'music'),
(2, 7, '2021-06-29', 3, 9, 'books'),
(2, 8, '2022-11-03', 1, 8, 'music'),
(3, 9, '2022-11-07', 1, 575, 'food'),
(3, 10, '2022-11-20', 2, 95, 'food'),
(3, 11, '2022-11-20', 1, 95, 'food'),
(4, 12, '2022-11-20', 2, 95, 'books'),
(4, 13, '2022-11-21', 1, 95, 'food'),
(4, 14, '2022-11-23', 4, 17, 'books'),
(5, 15, '2022-11-20', 1, 95, 'food'),
(5, 16, '2022-11-25', 2, 95, 'books'),
(5, 17, '2022-11-29', 1, 95, 'food');
参见SQL fiddle:http://sqlfiddle.com/#!17/3dc 69/1
我想得到以下内容:
在第一次购买图书的客户中(首先根据order_date
),作为product
(在本例中,客户ID为1和4),我希望获得:
A)这一群体购买书籍的平均值quantity
(在本例中为2.25,即1、2、2和4的平均值);
B)每次购买的总金额revenue
(在本例中为152)。
我尝试使用几个CTE来实现这一点。以下是我的尝试:
WITH all_orders AS (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY o.user_id ORDER BY o.order_date) AS row_num
FROM
orders o
),
first_product_is_books AS (
SELECT
DISTINCT(user_id) AS usr_id
FROM
all_orders
WHERE product = 'books' AND row_num = 1
),
temp_results AS (
SELECT
*
FROM
all_orders ao
JOIN
first_product_is_books AS fp
ON ao.user_id = fp.usr_id
)
SELECT
avg(quantity)
, sum(revenue)
FROM
temp_results tr
WHERE
tr.product = 'books'
参见fiddle:http://sqlfiddle.com/#!17/3dc 69/1
这适用于玩具数据集,但不适用于生产数据集,其中表约有400,000条记录。我认为这个查询是hacky,并没有真正优化。有没有更有效的方法?
4条答案
按热度按时间qv7cva1a1#
使用
DISTINCT ON
更简单:fiddle
哪种查询样式最有效主要取决于基数。总共有多少行,有多少用户,有多少书籍订单,有多少书籍的初始订单,平均行大小,平均大小为
product
。如果还有一个表
users
,每个相关的user_id
保存一行,则可以更简单,更快。你需要一个索引来支持查询。最好是
(user_id, order_date, product)
。同样,最好的指数取决于上述未公开的细节。而且
(user_id, order_date)
必须是唯一的,否则就有歧义。请参阅:
s5a0g9ez2#
这个怎么样?
uttx8gqw3#
这个版本的查询更容易阅读。
piztneat4#
你的问题的逻辑是有缺陷的(下面的所有代码都可以在fiddle here上找到)!
您想要计算两个用户(1和4)的两本书的平均购买量,但这四次购买的总收入不是152,而是323!
这是由计算(见表人口在小提琴)
323是两个用户的总收入的正确总和。
152 = 15 + 25 + 95 + 17,即计算中没有考虑数量!
该表是根据您的数据构建和填充的。
然后,我运行了以下SQL:
测试结果:
这就是正确答案!