如何在sql中汇总动态期间的信息?
Posted
技术标签:
【中文标题】如何在sql中汇总动态期间的信息?【英文标题】:How to summarize information over the dynamic period in sql? 【发布时间】:2020-03-26 10:56:05 【问题描述】:我有一个包含订单和以下字段的表格:
create table orders2 (
orderID int,
customerID int,
date DateTime,
amount int)
engine=Memory;
每个客户每天可以下 0 个或多个订单。我需要创建一个 SQL 查询,该查询将为每个客户显示他/她在从客户下订单之日起的 3 天内完成了多少订单。
因此,对于每个客户,查询应该检测第一个订单的日期,然后计算从第一个日期起 3 天后的日期,然后过滤行以仅接受日期在给定范围内的订单,然后在该时间段内执行订单计数(orderID)。目前,我只能检测每个客户的第一个订单日期。
SELECT
O.customerID,
O.date AS first_day,
COUNT(O.orderID) AS first_day_orders_num,
SUM(O.amount) AS first_day_amount
FROM orders2 AS O
INNER JOIN
(
SELECT
customerID,
MIN(date) AS first_date
FROM orders2
GROUP BY customerID
) AS I ON (O.customerID = I.customerID) AND (O.date = I.first_date)
GROUP BY
O.customerID,
O.date
【问题讨论】:
用您正在使用的数据库标记您的问题。 抱歉,您能否展示一下您努力解决问题的结果,而不仅仅是提出问题 @vladimir 我能够计算每个客户在他/她的第一个订单当天的订单数量和金额总和: 请查看我更新的问题。但我不明白如何在从每个客户的first_day
开始到first_day
后 3 天结束的时间段内获得类似的结果。
【参考方案1】:
我真的不明白你需要什么结果。可能它可以使用数组来解决。
这是使用 vanilla sql 的解决方案
select customerID, min(first_date), sum(num_orders_per_day)
from (
select customerID, date, min(date) first_date, count() num_orders_per_day
from orders2
group by customerID, date
having date <= first_date + interval 3 days
)
group by customerID
【讨论】:
谢谢!我已将这部分:date <= first_date + interval 3 days
替换为:date <= addDays(first_date, 3)
,它完全符合我的预期。
是的,x + interval 3 day / x + toIntervalDay(3) / addDays(x , 3) / 是同义词,但我更喜欢interval 3 day
,因为它对我来说更具可读性。【参考方案2】:
您可以使用窗口函数来获取第一个订单日期:
select o.CustomerID, count(*) as num_orders_3_days
from (select o.*, min(date) over (partition by CustomerID) as min_date
from orders o
) o
where date < min_date + interval '3 day'
group by CustomerID;
【讨论】:
很遗憾,Clickhouse 好像不支持窗口功能...【参考方案3】:试试这个查询:
SELECT customerID, orders_count
FROM (
SELECT customerID,
arraySort(x -> x.1, groupArray((date, orderID))) sorted_date_per_order_pairs,
sorted_date_per_order_pairs[1].1 + INTERVAL 3 day AS end_date,
arrayFilter(x -> x.1 < end_date, sorted_date_per_order_pairs) orders_in_period,
length(orders_in_period) orders_count
FROM orders2
GROUP BY customerID);
【讨论】:
谢谢!这个解决方案效果很好,但是使用 vanilla SQL 的方法更具可读性和更容易理解。 @kohek 欢迎 ;) 只需检查一下 - 您确定 Denis 的“vanilla sql”工作正常吗? “香草脚本”的结果不应与“数组脚本”的结果相同。 我检查了我的桌子,结果似乎和我预期的一样......以上是关于如何在sql中汇总动态期间的信息?的主要内容,如果未能解决你的问题,请参考以下文章
如何在anylogic中模拟期间动态更改资源池的班次组大小?