繁体   English   中英

在当前行之后和之前创建附加日期并基于它创建新列

[英]create additional date after and before current row and create new column based on it

可以说我有这种数据

create table example
(cust_id VARCHAR, product VARCHAR, price float, datetime varchar);

insert into example (cust_id, product, price, datetime)
VALUES
('1', 'scooter', 2000, '2022-01-10'),
('1', 'skateboard', 1500, '2022-01-20'),
('1', 'beefmeat', 300, '2022-06-08'),
('2', 'wallet', 200, '2022-02-25'),
('2', 'hairdryer', 250, '2022-04-28'),
('3', 'skateboard', 1600, '2022-03-29')

我想制作一些额外的行,然后根据这些额外的行制作新的列

我的期望 output 会喜欢这个

客户编号 总价 日期 活跃
1个 3500 2022-01 积极的
1个 0 2022-02 积极的
1个 0 2022-03 积极的
1个 0 2022-04 不活跃
1个 0 2022-05 不活跃
1个 300 2022-06 积极的
1个 0 2022-07 积极的
2个 0 2022-01 不活跃
2个 200 2022-02 积极的
2个 0 2022-03 积极的
2个 250 2022-04 积极的
2个 0 2022-05 积极的
2个 0 2022-06 积极的
2个 0 2022-07 不活跃
3个 0 2022-01 不活跃
3个 0 2022-02 不活跃
3个 1600 2022-03 积极的
3个 0 2022-04 积极的
3个 0 2022-05 积极的
3个 0 2022-06 不活跃
3个 0 2022-07 不活跃

规则是这样的

  1. 客户进行交易的第一个月称为活跃,在此交易之前称为不活跃。
    例如:第 2 个月的第一笔交易,然后第 2 个月活跃,第 1 个月不活跃(查看 cust_id 2 和 3)
  2. 如果超过 2 个月没有交易,则下个月不活跃,直到有新的交易活跃。
    例如:如果第 1 个月的最后一笔交易,则第 2 个月和第 3 个月不活跃,如果第 6 个月有新交易,则第 4 个月、第 5 个月不活跃(查看 cust_id 1 和 3)

好吧,我的第一个想法是使用这段代码,但我不知道下一步是什么

select *, 
    date_part('month', age(to_date(date, 'YYYY-MM'), to_date(lag(date) over (partition by cust_id order by date),'YYYY-MM')))date_diff
from(
    select 
        cust_id,
        sum(price)total_price,
        to_char(to_date(datetime, 'YYYY-MM-DD'),'YYYY-MM')date
    from example
    group BY
        cust_id,
        date
    order by 
    cust_id, 
    date)test

我愿意接受任何建议

尝试以下,查询评论中的解释:

/* use generate_series to generate a series of dates
   starting from the min date of datetime up to the 
   max datetime with one-month intervals, then do a 
   cross join with the distinct cust_id to map each cust_id 
   to each generated date.*/
WITH cust_dates AS
(
  SELECT EX.cust_id, to_char(dts, 'YYYY-mm') dts
  FROM generate_series 
        (
         (SELECT MIN(datetime)::timestamp FROM example), 
         (SELECT MAX(datetime)::timestamp + '2 month'::interval  FROM example),
         '1 month'::interval
        ) dts
  CROSS JOIN (SELECT DISTINCT cust_id FROM example) EX
),
/* do a left join with your table to find prices
   for each cust_id/ month, and aggregate for cust_id, month_date
   to find the sum of prices for each cust_id, month_date.
*/
monthly_price AS
(
  SELECT CD.cust_id,
       CD.dts AS month_date,
       COALESCE(SUM(price), 0) total_price
  FROM cust_dates CD LEFT JOIN example EX
  ON CD.cust_id = EX.cust_id AND 
     CD.dts = to_char(EX.datetime, 'YYYY-mm')
  GROUP BY CD.cust_id, CD.dts
)
/* Now, we have the sum of monthly prices for each cust_id,
   we can use the max window function with "ROWS BETWEEN 2 PRECEDING AND CURRENT ROW"
   to check if one of the (current month or the previous two months) has a sum of prices > 0.
*/
SELECT cust_id, month_date, total_price,
  CASE MAX(total_price) OVER 
      (PARTITION BY cust_id ORDER BY month_date 
       ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
    WHEN 0 THEN 'inactive' 
    ELSE 'active'
  END AS is_active
FROM monthly_price
ORDER BY cust_id, month_date

看演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM