带有SQL的Fifo Inventory

时间:2015-07-27 16:05:18

标签: sql sql-server sql-server-2008 fifo

我需要对第一张表进行一次调整,因为存在负面问题点,我需要将净值表视为第一次发行的借方。 E.g:

FechaEmi Cuenta PtosEmi PtosCan
30/06/2015  1   100     0
31/07/2015  1   120     0
31/08/2015  1   130     0
31/08/2015  1   0       55
30/09/2015  1   50      0
31/10/2015  1   30      0
30/11/2015  1   70      0
31/12/2015  1   95      0
31/01/2016  1   50      0
29/02/2016  1   0       74
31/03/2016  1   50      0
30/04/2016  1   15      0
30/06/2015  2   20      0
31/07/2015  2   30      0
31/08/2015  2   40      0
30/09/2015  2   350     0
30/06/2015  3   150     0
31/07/2015  3   120     0
31/08/2015  3   0       56
31/08/2015  3   220     0
30/06/2015  4   70      0
31/07/2015  4   134     0
31/08/2015  4   12      0
30/06/2015  5   97      0
31/07/2015  5   130     0
31/08/2015  5   15      0
30/09/2015  5   135     0
31/10/2015  5   20      0
30/11/2015  5   140     0
31/12/2015  5   25      0
31/01/2016  5   145     0
29/02/2016  5   0       25

其中:

FechaEmi =日期;

CUENTA = ID;

PtosEmi =问题点;

PtosCan =取消分数

我想要这张桌子

FechaEmi    Cuenta  PtosEmi
30/06/2015  1   0
31/07/2015  1   91
31/08/2015  1   130
30/09/2015  1   50
31/10/2015  1   30
30/11/2015  1   70
31/12/2015  1   95
31/01/2016  1   50
31/03/2016  1   50
30/04/2016  1   15
30/06/2015  2   20
31/07/2015  2   30
31/08/2015  2   40
30/09/2015  2   350
30/06/2015  3   94
31/07/2015  3   120
31/08/2015  3   220
30/06/2015  4   70
31/07/2015  4   134
31/08/2015  4   12
30/06/2015  5   72
31/07/2015  5   130
31/08/2015  5   15
30/09/2015  5   135
31/10/2015  5   20
30/11/2015  5   140
31/12/2015  5   25
31/01/2016  5   145

我有这个代码。问题是,在没有问题点的日期中扣除的点数没有做任何事情。你怎么能建议我改变那个查询?谢谢!

with cte as( 
select Fechaemi, Cuenta,PtosEmi,PtosCan
,row_number() over (partition by Fechaemi,Cuenta order by Fechaemi,Cuenta) as rank 
from emision) 
select a.Fechaemi, a.Cuenta,a.PtosEmi - coalesce(b.PtosCan, 0) stock 
from cte a 
left join cte b on 
a.FechaEmi= b.FechaEmi and a.Cuenta = b.Cuenta and a.rank = b.rank - 1 
where a.PtosEmi - coalesce(b.PtosCan, 0) > 0 order by a.cuenta asc, a.fechaemi asc

2 个答案:

答案 0 :(得分:1)

SQL FIDDLE DEMO

with totalPay as( 
    SELECT Cuenta, SUM(PtosCan) TotalPayment
    FROM emision
    GROUP BY Cuenta
),
totalDebt as (
    SELECT FechaEmi, Cuenta, (SELECT SUM(PtosEmi) 
                              FROM emision e2 
                              WHERE e2.FechaEmi <= e.FechaEmi
                              AND   e2.Cuenta = e.Cuenta                          
                             ) AS TotalDebt
    FROM emision e
    WHERE   e.PtosEmi <> 0
)
select  
    e.FechaEmi, 
    e.Cuenta, 
    e.PtosEmi, 
    td.TotalDebt, 
    tp.TotalPayment,
    CASE 
        WHEN td.TotalDebt < tp.TotalPayment THEN 0
        WHEN td.TotalDebt - tp.TotalPayment > PtosEmi THEN PtosEmi
        ELSE td.TotalDebt - tp.TotalPayment
    END Remaining
FROM 
    totalDebt  td inner join 
    totalPay tp on td.Cuenta = tp.Cuenta inner join
    emision e on td.FechaEmi = e.FechaEmi AND td.Cuenta = e.Cuenta
WHERE 
    e.PtosEmi <> 0

答案 1 :(得分:1)

可能不是最优雅但最明确的方式:

WITH 
PtosEmi AS(
  SELECT FechaEmi, cuenta, SUM(PtosEmi) as PtosEmi
  FROM table1
  GROUP BY FechaEmi, cuenta),
PtosCan AS (
  SELECT MIN(FechaEmi) as FechaEmi, cuenta, SUM(PtosCan) as PtosCan 
  FROM table1
  GROUP BY cuenta)
SELECT 
  e.FechaEmi, 
  e.cuenta, 
  e.ptosemi, 
  c.ptoscan,
  e.ptosemi - COALESCE(c.ptoscan, 0) total
FROM 
  PtosEmi e LEFT JOIN 
  PtosCan c ON e.FechaEmi = c.FechaEmi AND e.cuenta = c.cuenta
ORDER BY e.cuenta, e.FechaEmi

这是基于这样的假设:在给予cuenta的任何内容之前你不能取消。

此外,如果您最初取消的项目与最初发布的项目相比更多,则总值将为负数。

http://sqlfiddle.com/#!6/9ac40/11

<强>更新

因为你想逐行减少取消,这里更新查询:

WITH 
ptosemi AS(
    SELECT FechaEmi, cuenta, 
           PtosEmi as PtosEmi,
           SUM(PtosEmi) OVER (PARTITION BY cuenta ORDER BY FechaEmi) runsum 
    FROM table1),
PtosCan AS (
    SELECT cuenta, SUM(PtosCan) as PtosCan 
    FROM table1
    GROUP BY cuenta)
SELECT 
  e.FechaEmi, 
  e.cuenta, 
  e.ptosemi, 
  e.runsum,
  c.ptoscan,
  CASE 
    WHEN e.runsum <= c.ptoscan
    THEN 0 
    WHEN c.ptoscan BETWEEN e.runsum - e.ptosemi AND e.runsum
    THEN e.runsum - COALESCE(c.ptoscan, 0)
    ELSE e.ptosemi END total
FROM 
 ptosemi e LEFT JOIN 
 PtosCan c ON e.cuenta = c.cuenta
ORDER BY e.cuenta, e.FechaEmi

http://sqlfiddle.com/#!6/8036c2/25