我正在使用现有的电子商务数据库。实际上,这个过程通常是在excel中完成的,但是我们想直接用postgresql(版本10.6)中的查询来尝试。
我们将在一年内至少购买过一次的人定义为活跃客户。这意味着,如果我分析2020年第22周,一个活跃的客户将是自2019年第22周以来至少购买过一次的客户。
我要每年(2020年)每周的产量。基本上我需要的是。。。
select
email,
orderdate,
id
from
orders_table
where
paid = true;
|---------------------|-------------------|-----------------|
| email | orderdate | id |
|---------------------|-------------------|-----------------|
| email1@email.com |2020-06-02 05:04:32| Order-2736 |
|---------------------|-------------------|-----------------|
我无法创建新表。我想看到这样的输出:
Year| Week | Active customers
2020| 25 | 6978
2020| 24 | 3948
2条答案
按热度按时间rmbxnbpk1#
取决于是否有
year
以及week
列可以使用OVER (PARTITION BY ...)
与extract
:它应该按年度和周存储所有订单,从而显示一年中每周的总计数,其中支付是真实的。
参考文献:
https://www.postgresql.org/docs/9.1/tutorial-window.html
https://www.postgresql.org/docs/8.1/functions-datetime.html
bxfogqkk2#
如果我分析2020年第22周,那么一个活跃的客户将是自2019年第22周以来至少购买过一次的客户。
你这边的问题
此方法存在一些不明确/问题:
是否包括或排除“2020年第22周”(我将其排除在下面,以便更接近“一年”。)
一年可以有52或53个完整的星期。根据当前日期,计算是以52或53周为基础的,可能会产生几乎2%的偏差!
如果从“去年的同一日期”开始计算时间范围,则由于闰年的原因,误差幅度仅为1/365或~0.3%。
一个固定的“365天”(或366天)将完全消除偏差。
sql方面的问题
不幸的是,窗口函数当前不允许
DISTINCT
关键词(有充分的理由)。所以某种形式:.. 触发器:
这个
GROUPS
关键字只被添加在postgres 10,否则就是我们需要的。更重要的是,你的奇数帧定义甚至无法准确地工作,因为要考虑的周数并不总是52,如上所述。
所以我们必须自己动手。
解决方案
下面简单地生成所有感兴趣的周数,并计算每个周的不同客户数。很简单,只是日期数学从来都不简单。但是,根据设置的细节,可能会有更快的解决方案(我还有其他一些想法。)
要报告的时间范围可能会更改。下面是一个辅助函数,用于生成给定年份的周数:
电话:
它每周返回一行,但在当前年份的当前周停止(空置以备将来使用。)
计算基于以下事实:
一年中的第一个iso周总是包含1月4日。
最后一个iso周不能在12月28日之后开始。
实际周数是使用
WITH ORDINALITY
. 请参见:带有元素编号的postgresql unnest()
不管怎样,我坚持
timestamp
避免timestamptz
为此目的。请参见:在postgresql中生成两个日期之间的时间序列
函数还返回一周开始的时间戳(
week_start
)我们手头的问题不需要。但我保留了它,以使函数在总体上更有用。使主查询更简单:
db<>在这里摆弄
cte
weekly_customer
每个日历周向唯一的客户折叠一次,因为重复条目只是我们计算的噪音。它在主查询中被多次使用。截止条件再次基于1月4日。调整到你的实际报告期。实际的计数是用一个低关联的子查询完成的。可能是一个
LEFT JOIN LATERAL ... ON true
相反。请参见:在postgresql中,横向查询和子查询有什么区别?
使用行值比较简化范围定义。请参见:
“where(col1,col2)<(val1,val2)”的sql语法术语