此解决方案主要是标准 SQL,适用于最新版本的 MySQL、PostgreSQL 等。
有几种方法可以做到这一点。
这是一个简单聚合问题的组合,也是一个窗口函数问题,我们希望按日期引用每个客户/购物车的基本聚合结果中的相邻行。窗口函数 (LEAD) 仅引用基于 PARTITION BY 和 ORDER BY 子句的下一个后续结果行。
这是一个简单的测试用例。它为所有客户生成所有行,每个行都有下一个购物车总数。请注意最后一行包含 null,因为没有 next 购物车总数。
它比您要求的要多一些,但包含一些有用的细节,说明如何轻松生成更复杂的结果。我们可以根据需要将其限制为特定客户和特定订单。
其中一些可以稍微简化,具体取决于约束和您的数据库如何处理功能依赖性。
如果cart_id是table1的主键,不仅仅是唯一的,我们可以再简化一点。
PG test case here
SELECT t1.cart_id
, t1.customer_id
, t1.date
, SUM(quantity * price_per_unit_cents)
, LEAD(SUM(quantity * price_per_unit_cents)) OVER (PARTITION BY t1.customer_id ORDER BY t1.date, t1.cart_id) AS next
, ROW_NUMBER() OVER (PARTITION BY t1.customer_id ORDER BY t1.date, t1.cart_id) AS n
FROM table1 AS t1
JOIN table2 AS t2
ON t1.cart_id = t2.cart_id
GROUP BY t1.customer_id, t1.cart_id
ORDER BY t1.customer_id, date
;
结果(用更多数据显示行为):
设置:
CREATE TABLE table1 (
customer_id int -- Customer id
, cart_id int primary key -- cart id
, date Date -- of the cart checkout
);
CREATE TABLE table2 (
cart_id int -- cart id
, item int -- Item in a given cart
, quantity int -- Quantity of item in a cart
, price_per_unit_cents decimal(7,2) -- Price per single unit of item in a cart
);
INSERT INTO table2 VALUES
(1, 1, 5, 100.00)
, (1, 2, 8, 50.00)
, (2, 1, 5, 110.00)
, (2, 2, 7, 60.00)
, (3, 1, 5, 300.00)
, (3, 2, 8, 50.00)
, (4, 1, 5, 310.00)
, (4, 2, 7, 60.00)
, (5, 1, 2, 110.00)
, (5, 2, 3, 60.00)
;
INSERT INTO table1 VALUES
(1, 1, current_date)
, (1, 2, current_date + INTERVAL '1' DAY)
, (2, 3, current_date)
, (2, 4, current_date + INTERVAL '2' DAY)
, (1, 5, current_date + INTERVAL '3' DAY)
;