SQL 先进先出积分
SQL First In First Out Loyalty Point
开发人员和分析师。我在 SQL 方面有一些经验,并且求助于类似的帖子。但是,这有点小众。预先感谢您的帮助。
我有以下数据集(已编辑。抱歉)
Setup
CREATE TABLE CustomerPoints
(
CustomerID INT,
[Date] Date,
Points INT
)
INSERT INTO CustomerPoints
VALUES
(1, '20150101', 500),
(1, '20150201', -400),
(1, '20151101', 300),
(1, '20151201', -400)
需要转成(已编辑。之前table中的数字不正确)
积分为正数为积分,积分为负数为兑换积分。由于 FIFO(先进先出概念),在第二批花费的点数 (-400) 中,100 点来自 20150101(英国格式)获得的点数,300 点来自 20151101。
目标是为每个客户计算在赚取收入后的 x 和 y 个月内花费的积分数。再次感谢您的帮助。
我已经回答过类似的问题here and
您需要将单个单元获得和兑换的点数分解,然后将它们耦合,这样每个获得的点数都会匹配一个兑换点数。
对于这些匹配行中的每一行,计算从赚取到赎回所经过的月份,然后将其全部汇总。
对于 FN_NUMBERS(n) 它是一个计数 table,看看我在上面链接的其他答案。
;with
p as (select * from CustomerPoints),
e as (select * from p where points>0),
r as (select * from p where points<0),
ex as (
select *, ROW_NUMBER() over (partition by CustomerID order by [date] ) rn
from e
join FN_NUMBERS(1000) on N<= e.points
),
rx as (
select *, ROW_NUMBER() over (partition by CustomerID order by [date] ) rn
from r
join FN_NUMBERS(1000) on N<= -r.points
),
j as (
select ex.CustomerID, DATEDIFF(month,ex.date, rx.date) mm
from ex
join rx on ex.CustomerID = rx.CustomerID and ex.rn = rx.rn and rx.date>ex.date
)
-- use this select to see points redeemed in current and past semester
select * from j join (select 0 s union all select 1 s ) p on j.mm >= (p.s*6)+(p.s) and j.mm < p.s*6+6 pivot (count(mm) for s in ([0],[2])) p order by 1, 2
-- use this select to see points redeemed with months detail
--select * from j pivot (count(mm) for mm in ([0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) p order by 1
-- use this select to see points redeemed in rows per month
--select CustomerID, mm, COUNT(mm) PointsRedeemed from j group by CustomerID, mm order by 1
默认查询输出,0为0-6个月,1为7-12(赎回年龄)
CustomerID 0 1
1 700 100
第二次查询的输出,0..12是赎回年龄
CustomerID 0 1 2 3 4 5 6 7 8 9 10 11 12
1 0 700 0 0 0 0 0 0 0 0 0 100 0
第三个查询的输出,是以月为单位的赎回年龄
CustomerID mm PointsRedeemed
1 1 700
1 11 100
再见
开发人员和分析师。我在 SQL 方面有一些经验,并且求助于类似的帖子。但是,这有点小众。预先感谢您的帮助。
我有以下数据集(已编辑。抱歉)
Setup
CREATE TABLE CustomerPoints
(
CustomerID INT,
[Date] Date,
Points INT
)
INSERT INTO CustomerPoints
VALUES
(1, '20150101', 500),
(1, '20150201', -400),
(1, '20151101', 300),
(1, '20151201', -400)
需要转成(已编辑。之前table中的数字不正确)
积分为正数为积分,积分为负数为兑换积分。由于 FIFO(先进先出概念),在第二批花费的点数 (-400) 中,100 点来自 20150101(英国格式)获得的点数,300 点来自 20151101。
目标是为每个客户计算在赚取收入后的 x 和 y 个月内花费的积分数。再次感谢您的帮助。
我已经回答过类似的问题here and
您需要将单个单元获得和兑换的点数分解,然后将它们耦合,这样每个获得的点数都会匹配一个兑换点数。
对于这些匹配行中的每一行,计算从赚取到赎回所经过的月份,然后将其全部汇总。
对于 FN_NUMBERS(n) 它是一个计数 table,看看我在上面链接的其他答案。
;with
p as (select * from CustomerPoints),
e as (select * from p where points>0),
r as (select * from p where points<0),
ex as (
select *, ROW_NUMBER() over (partition by CustomerID order by [date] ) rn
from e
join FN_NUMBERS(1000) on N<= e.points
),
rx as (
select *, ROW_NUMBER() over (partition by CustomerID order by [date] ) rn
from r
join FN_NUMBERS(1000) on N<= -r.points
),
j as (
select ex.CustomerID, DATEDIFF(month,ex.date, rx.date) mm
from ex
join rx on ex.CustomerID = rx.CustomerID and ex.rn = rx.rn and rx.date>ex.date
)
-- use this select to see points redeemed in current and past semester
select * from j join (select 0 s union all select 1 s ) p on j.mm >= (p.s*6)+(p.s) and j.mm < p.s*6+6 pivot (count(mm) for s in ([0],[2])) p order by 1, 2
-- use this select to see points redeemed with months detail
--select * from j pivot (count(mm) for mm in ([0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) p order by 1
-- use this select to see points redeemed in rows per month
--select CustomerID, mm, COUNT(mm) PointsRedeemed from j group by CustomerID, mm order by 1
默认查询输出,0为0-6个月,1为7-12(赎回年龄)
CustomerID 0 1
1 700 100
第二次查询的输出,0..12是赎回年龄
CustomerID 0 1 2 3 4 5 6 7 8 9 10 11 12
1 0 700 0 0 0 0 0 0 0 0 0 100 0
第三个查询的输出,是以月为单位的赎回年龄
CustomerID mm PointsRedeemed
1 1 700
1 11 100
再见