SQL 中的 Fifo 方法

Fifo Method in SQL

我必须在 SQL 中实现类似于 FIFO 方法的东西。问题是我在不同的月份发行了积分,同时我在其他日期交换了积分。问题是我必须知道积分是多少个月前发行的,直到兑换为止。所以首先要兑换的积分是老年人,但如果 2014 年 6 月 30 日发放了 200 分,2014 年 7 月 31 日发放了 100 分,2014 年 8 月 31 日发放了 250 分。 200 点有 2 个月的开发(6 月的 200)和 50 点有 1 个月的开发(7 月发布的 100 中的 50)。我该如何编码?

我留下一些table以便更好地理解!

谢谢

Date of issue   Number of account   Issued points
30-abr                    1            300
31-may                    1             50
30-jun                    1            100
30-jun                    2            100
30-jun                    3            120
31-may                    4             20
30-jun                    4            200



Date of exchange    Number of account   Exchanged points
30-jun                     1                  250
31-jul                     1                  200
31-jul                     3                   30
30-jun                     4                   30
31-jul                     2                   10
30-jun                     3                   30
31-ago                     4                   10

最后 table 我需要的是。

Issue date  Months after issue  Exchanged points
30-abr           2,00               250,00
30-abr           3,00                50,00
31-may           2,00                50,00
31-may           1,00                20,00
30-jun           1,00               100,00
30-jun           1,00                30,00
30-jun           0,00                10,00
30-jun           1,00                10,00
30-jun           0,00                30,00
30-jun           2,00                10,00

编辑:添加示例以阐明帐户 1 的问题:

3个不同月份发布的积分:

Date of issue   Points
30-apr          300
31-may           50
30-jun          100

这些交换了 2 次:

Date of exchange    Points
30-jun              250
31-jul              200

由于交换是从不同月份发放的积分进行的,结果应该是4个动作,所以最早的积分首先被使用:

Date of exchange    Date of issue   Points    Months
30-jun              30-apr          250       2
31-jul              30-apr           50       3
31-jul              31-may           50       2
31-jul              30-jun          100       1

我试了一下这个 SQL returns 正确的结果。不知怎的,我觉得它可能有错误,但至少这是一个开始的地方(或者完全错误的方法):

;with I as (
  select 
    date,
    points,
    account,
    isnull((select sum(points) from issue i2 
       where i2.account = i1.account and i2.date < i1.date),0) as Cumulative
  from
    issue i1
),
E as (
  select 
    date,
    points,
    account,
    isnull((select sum(points) from Exchange e2 
       where e2.account = e1.account and e2.date < e1.date),0) as Cumulative
  from
    Exchange e1
),
X as ( 
  select
  I.Account,
  I.Date as IDate, I.Points as IPoints, I.Cumulative as ICumulative,
  E.Date as EDate, E.Points as EPoints, E.Cumulative as ECumulative
  from I 
  join E on I.account = E.account 
        and I.Points + I.Cumulative > E.Cumulative
        and E.Cumulative + E.Points > I.Cumulative
)

select 
  Account, IDate, datediff(month, IDate, EDate) as After,
  case when EPoints + ECumulative < IPoints + ICumulative 
      then EPoints 
      else IPoints + ICumulative - ECumulative end
  - case when ICumulative > ECumulative 
      then (ICumulative - ECumulative) 
      else 0 end as Points
from X
order by IDate, EDate

前 2 个 CTE(I 和 E)计算 运行 点总数,第 3 个 (X) 根据发布和交换的内容收集所需的行。计算最终 Points 列的公式只是反复试验,所以我不能 100% 确定它在所有情况下都是准确的:)

您可以在 SQL Fiddle

中尝试