根据获得的用户积分表,我需要计算累积积分的六个月半衰期。也就是说,过去6个月赚取的所有积分均为100%,6-12个月为50%,12-18个月为25%等。
这是我使用CTE的最佳尝试:
DECLARE @t AS TABLE (
ID int NOT NULL,
DT SMALLDATETIME NOT NULL,
POINTS int NOT NULL,
UserId INT NOT null,
POINTS_TOTAL INT NOT NULL)
INSERT INTO @t
VALUES (1, '1/1/2010', 20, 1, 20)
,(5, '7/1/2010', 30, 1, 50)
,(7, '1/1/2011', 10, 1, 60)
,(8, '7/1/2011', 15, 1, 75)
,(9, '12/25/2011', 15, 1, 90)
;WITH ctePts AS
(SELECT t.*, POINTS AS Decay
FROM @t AS t
WHERE t.DT > DATEADD(mm, 6, GETUTCDATE())
UNION ALL
SELECT t.ID, t.DT, t.POINTS, t.UserId, t.POINTS_TOTAL, CAST(ctePts.Decay * 0.5 + t.POINTS AS INT) AS Decay
FROM ctePts
INNER JOIN @t AS t
ON t.UserId = ctePts.UserId
AND t.DT <= ctePts.DT AND t.DT > DATEADD(mm, 6, ctePts.DT)
)
SELECT *
FROM ctePts
最终表格中有一个HALF_LIFE列,其中包含该用户获得的所有积分的调整总和。我应该能够运行以下查询来获取用户当前点状态(针对任何给定时间点调整为半衰期衰减的总累积点数):
SELECT UserIdInt, POINTS, POINTS_HALFLIFE FROM
(SELECT UserIdInt,
ISNULL(p.POINTS_TOTAL,0) AS POINTS, ISNULL(p.POINTS_HALFLIFE,0) POINTS_HALFLIFE,
ROW_NUMBER() OVER (Partition BY UserIdInt ORDER BY p.ID DESC) AS rownum
FROM dbo.USER_POINTS p ) a
WHERE rownum = 1
答案 0 :(得分:2)
这是你需要的吗?
SELECT *,
POINTS / POWER(2E0, ( ( DATEDIFF(MONTH, DT, GETUTCDATE()) - 1 +
CASE
WHEN DAY(DT) <= DAY(GETUTCDATE()) THEN 1
ELSE 0
END ) / 6 ))
AS POINTS_HALFLIFE
FROM @t
返回
ID DT POINTS UserId POINTS_TOTAL POINTS_HALFLIFE
----------- ----------------------- ----------- ----------- ------------ ----------------------
1 2010-01-01 00:00:00 20 1 20 2.5
5 2010-07-01 00:00:00 30 1 50 7.5
7 2011-01-01 00:00:00 10 1 60 5
8 2011-07-01 00:00:00 15 1 75 15
9 2011-12-25 00:00:00 15 1 90 15
答案 1 :(得分:0)
我不完全理解这个问题,但我认为你是按用户ID来查找,所以按用户ID分组。如果您不需要按用户ID进行分组,则只需在select和group by中删除它。
select base.UserId, SUM([full].[POINTS]) as [fullPoints], SUM([half].[POINTS])/2 as [halfPoints]
, SUM([quarter].[POINTS])/4 as [quarterPoints]
, (SUM([full].[POINTS]) + SUM([half].[POINTS])/2 + SUM([quarter].[POINTS])/4 ) as [totalPoints]
from @t as [base]
left outer join @t as [full]
on base.ID = [full].ID
and DATEDIFF(MM, [full].DT, GETDATE()) <= 6
left outer join @t as [half]
on base.ID = [half].ID
and DATEDIFF(MM, [half].DT, GETDATE()) > 6
and DATEDIFF(MM, [half].DT, GETDATE()) <= 12
left outer join @t as [quarter]
on base.ID = [quarter].ID
and DATEDIFF(MM, [quarter].DT, GETDATE()) > 12
group by base.UserId