【问题标题】:Calculating a new column using two other columns by considering time decaying factor通过考虑时间衰减因子使用其他两列计算新列
【发布时间】:2017-11-20 01:33:46
【问题描述】:

我的问题有点棘手,如果有人帮助我,我将不胜感激。

我有下表,我想根据用户在之前的比赛中获得的分数来计算最后一列(当前比赛之前的智力资本)。分数随时间按以下公式衰减:

分数*e^(-t/500)

t 是从上次比赛过去的天数。如果用户在当前比赛之前参加过不止一场比赛,我们会添加分数。

下表说明了我要计算的内容。

competitionsId  UserId	date  score 	intellectual-capital-prior-to-current 
1	100	1/1/2015	3000	
1	200	1/1/2015	3000	
1	300	1/1/2015	3000	
1	400	1/1/2015	3000	
2	100	1/5/2015	4000	3000* POWER(e, -4/500)
2	400	1/5/2015	4000	3000* POWER(e, -4/500)
3	100	1/10/2015	1200	3000* POWER(e,-9/500)+ 4000*POWER(e,-5/500)
3	300	1/10/2015	1200	3000*POWER(e,-9/500)
3	400	1/10/2015	1200	3000* POWER(e, -9/500) + 4000*POWER(e,-5/500)
4	200	1/20/2015	1000	3000*POWER(e,-19/500)
4	300	1/20/2015	1000	3000*POWER(e,-19/500)+ 1200*POWER(e,-10/500)

例如在比赛 3 之前,user100 参加了比赛 2 和比赛 1。她在比赛 1 中的得分为 3000,因此考虑衰减因子,我们有 3000*e^(-9/500),她在比赛 2 中的得分为4000 所以考虑衰减因子我们有 4000*e^(-5/500)。因此user100在比赛3中的智力资本为:3000*e^(-9/500) + 4000*e^(-5/500)

【问题讨论】:

  • 您使用的是什么数据库? “sql”并没有告诉我们足够的信息,因为每个 dbms 平台对一系列操作使用不同的语法。
  • @Used_By_Already 我在使用 sql
  • "I use sql".... SQL 是标准,而不是产品。请改用标签“sql-server”。
  • @Used_By_Already 感谢您的澄清。我编辑了我的 tangs,我将在下一个问题中使用 sql-server 标签。

标签: sql-server formula calculated-columns


【解决方案1】:

以下内容可能会帮助您进行所需的计算。我不完全确定e 在您的公式中代表什么,但是通过一些窗口函数,我们可以获得所需的先前值并累积值。

DEMO at SQL Fiddle(MS SQL Server 2014 架构设置)

CREATE TABLE Table1
    ([competitionsId] int, [UserId] int, [date] datetime, [score] int, [note] varchar(45))
;

INSERT INTO Table1
    ([competitionsId], [UserId], [date], [score], [note])
VALUES
    (1, 100, '2015-01-01 00:00:00', 3000, '-'),
    (1, 200, '2015-01-01 00:00:00', 3000, '-'),
    (1, 300, '2015-01-01 00:00:00', 3000, '-'),
    (1, 400, '2015-01-01 00:00:00', 3000, '-'),
    (2, 100, '2015-01-05 00:00:00', 4000, '3000* POWER(e, -4/500)'),
    (2, 400, '2015-01-05 00:00:00', 4000, '3000* POWER(e, -4/500)'),
    (3, 100, '2015-01-10 00:00:00', 1200, '3000* POWER(e,-9/500)+ 4000*POWER(e,-5/500)'),
    (3, 300, '2015-01-10 00:00:00', 1200, '3000*POWER(e,-9/500)'),
    (3, 400, '2015-01-10 00:00:00', 1200, '3000* POWER(e, -9/500) + 4000*POWER(e,-5/500)'),
    (4, 200, '2015-01-20 00:00:00', 1000, '3000*POWER(e,-19/500)'),
    (4, 300, '2015-01-20 00:00:00', 1000, '3000*POWER(e,-19/500)+ 1200*POWER(e,-10/500)')
;

查询 1

with Primo as (
      select
              *
            , datediff(day,lead([date],1) over(partition by userid order by [date]),[date]) day_diff
      from Table1
      )
, Secondo as (
      select
              *
           , lag(day_diff,1) over(partition by userid order by [date]) t
           , lag(score,1) over(partition by userid order by [date]) prev_score
      from primo
      )
 select
        power(prev_score*1.0,t/500.0) x
      , sum(power(prev_score*1.0,t/500.0)) over(partition by userid order by [date]) y
      , competitionsId,UserId,date,score,day_diff,t,prev_score,note 
from secondo
;

Results

|      x |      y | competitionsId | UserId |                 date | score | day_diff |      t | prev_score |                                          note |
|--------|--------|----------------|--------|----------------------|-------|----------|--------|------------|-----------------------------------------------|
| (null) | (null) |              1 |    100 | 2015-01-01T00:00:00Z |  3000 |       -4 | (null) |     (null) |                                             - |
|    0.9 |    0.9 |              2 |    100 | 2015-01-05T00:00:00Z |  4000 |       -5 |     -4 |       3000 |                        3000* POWER(e, -4/500) |
|    0.9 |    1.8 |              3 |    100 | 2015-01-10T00:00:00Z |  1200 |   (null) |     -5 |       4000 |   3000* POWER(e,-9/500)+ 4000*POWER(e,-5/500) |
| (null) | (null) |              1 |    200 | 2015-01-01T00:00:00Z |  3000 |      -19 | (null) |     (null) |                                             - |
|    0.7 |    0.7 |              4 |    200 | 2015-01-20T00:00:00Z |  1000 |   (null) |    -19 |       3000 |                         3000*POWER(e,-19/500) |
| (null) | (null) |              1 |    300 | 2015-01-01T00:00:00Z |  3000 |       -9 | (null) |     (null) |                                             - |
|    0.9 |    0.9 |              3 |    300 | 2015-01-10T00:00:00Z |  1200 |      -10 |     -9 |       3000 |                          3000*POWER(e,-9/500) |
|    0.9 |    1.8 |              4 |    300 | 2015-01-20T00:00:00Z |  1000 |   (null) |    -10 |       1200 |  3000*POWER(e,-19/500)+ 1200*POWER(e,-10/500) |
| (null) | (null) |              1 |    400 | 2015-01-01T00:00:00Z |  3000 |       -4 | (null) |     (null) |                                             - |
|    0.9 |    0.9 |              2 |    400 | 2015-01-05T00:00:00Z |  4000 |       -5 |     -4 |       3000 |                        3000* POWER(e, -4/500) |
|    0.9 |    1.8 |              3 |    400 | 2015-01-10T00:00:00Z |  1200 |   (null) |     -5 |       4000 | 3000* POWER(e, -9/500) + 4000*POWER(e,-5/500) |

【讨论】:

  • 非常感谢@Used_By_Already。我感谢您的帮助。你是天才
  • 我尝试在 sql server 2008 中运行此查询。但出现以下错误:Msg 195, Level 15, State 10, Line 4 'lead' is not a known built-in function name。消息 195,级别 15,状态 10,第 10 行“滞后”不是可识别的内置函数名称。消息 102,级别 15,状态 1,第 16 行 'order' 附近的语法不正确。
  • mmmmmmmm 如果您运行的是旧版本,请对标签的选择非常挑剔。这使得它退出有点困难,因为你必须通过使用 row_number() 来模拟领先的效果,并在 rownumber 上加入 1,而且你可能也没有运行 sum()(不记得确切)
  • @ Used_By_Already 我正在安装 sql server 2016 。我希望它在里面运行。如果没有,我会向您询问更多详细信息。非常感谢 :)
  • v2016 确实具有所有需要的功能
猜你喜欢
  • 2018-05-04
  • 1970-01-01
  • 2011-11-28
  • 2017-02-20
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多