如何在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 &lt;= first_date + interval 3 days 替换为:date &lt;= 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中汇总动态期间的信息?的主要内容,如果未能解决你的问题,请参考以下文章

在表中动态记录 PLSql 语句

如何在 Ajax 请求期间在 JSF2 中动态添加组件

如何在anylogic中模拟期间动态更改资源池的班次组大小?

怎样查看Tomcat动态控制台信息

在 Django shell 会话期间获取 SQL 查询计数

如何MyBatis中使用动态SQL查询与注释