簡體   English   中英

SQL Server:累積總和,缺少日期

[英]SQL Server : cumulative sum, missing dates

我正在使用Microsoft SQL Server 2012。

我有一張包含商品交易記錄的表格:

artcode transdate     Qty       transactionvalue
------------------------------------------------
M100    2010-11-24    6.00      179.40
M100    2010-11-24    -6.00     -179.4
M100    2010-11-25    100.00    2900.00
M100    2010-11-26    -1.00     -29
M100    2010-11-26    -5.00     -145
M100    2010-11-26    -1.00     -29
M100    2010-11-29    -5.00     -145
M100    2010-11-29    -3.00     -87
M100    2010-11-29    -1.00     -29

通過此查詢,我設法按運行順序獲取了累積值:

SELECT 
    TransDate, ArtCode, CumulativeQuantity, CumulativeValue 
FROM 
    (SELECT
         ArtCode, 
         SUM(CAST(REPLACE(REPLACE(NULLIF(Qty, ''), ',', '.'), ' ', '') AS float)) OVER (PARTITION BY artcode ORDER BY transdate) AS CumulativeQuantity,
         SUM(CAST(REPLACE(REPLACE(NULLIF(TotCostPrice, ''), ',', '.'), ' ', '') AS FLOAT)) OVER (PARTITION BY artcode ORDER BY transdate) AS CumulativeValue,
         TransDate
     FROM
         stage_itemhistory 
     WHERE
         artcode = 'm100' AND stockaffect = 1) S 
GROUP BY
    TransDate, ArtCode, CumulativeQuantity, CumulativeValue

返回:

TransDate   ArtCode CumulativeQuantity  CumulativeValue
--------------------------------------------------------
2010-11-24  M100    0                   0
2010-11-25  M100    100                 2900
2010-11-26  M100    93                  2697
2010-11-29  M100    84                  2436

這與我所追求的非常接近,唯一缺少的是日期之間的間隔,即以前的日期的累積值。 所以它看起來像這樣:

TransDate   ArtCode CumulativeQuantity  CumulativeValue
--------------------------------------------------------
2010-11-24  M100    0                   0
2010-11-25  M100    100                 2900
2010-11-26  M100    93                  2697
2010-11-27  M100    93                  2697
2010-11-28  M100    93                  2697
2010-11-29  M100    84                  2436

任何和所有幫助將不勝感激! 先感謝您。

這比我想象的要難。 有人可能有一個更簡單的解決方案。 需要填寫artcode,並考慮不同artcode上的不同范圍。

declare @T table (artcode varchar(10), transdate date, Qty smallmoney, transactionvalue smallmoney);
insert into @T values 
       ('M100', '2010-11-24', 6.00, 179.40)
     , ('M100', '2010-11-24', -6.00, -179.4)
     , ('M100', '2010-11-25', 100.00, 2900.00)
     , ('M100', '2010-11-26', -1.00, -29)
     , ('M100', '2010-11-26', -5.00, -145)
     , ('M100', '2010-11-26', -1.00, -29)
     , ('M100', '2010-11-29', -5.00, -145)
     , ('M100', '2010-11-29', -3.00, -87)
     , ('M100', '2010-11-29', -1.00, -29)
     , ('M101', '2010-11-23', 6.00, 179.40)
     , ('M101', '2010-11-25', 100.00, 2900.00)
     , ('M101', '2010-11-26', -1.00, -29)
     , ('M101', '2010-11-26', -5.00, -145)
     , ('M101', '2010-11-26', -1.00, -29)
     , ('M101', '2010-11-30', -5.00, -145)
     , ('M101', '2010-11-30', -3.00, -87)
     , ('M101', '2010-11-30', -1.00, -29);
with limits as 
( select t.artcode, min(t.transdate) as startDate, max(t.transdate) as endtDate 
  from @T t 
  group by t.artcode
)
, dts as 
( select l.artcode, l.startDate as dt, l.startDate, l.endtDate
    from limits l 
  union all 
  select l.artcode, dateadd(day, 1, l.dt), l.startDate, l.endtDate
  from dts l 
  where dateadd(day, 1, l.dt) <= l.endtDate
)
select distinct dts.artcode, dts.dt
     , sum(isnull(t.Qty, 0))              over (partition by dts.artcode order by dts.dt) as Qty
     , sum(isnull(t.transactionvalue, 0)) over (partition by dts.artcode order by dts.dt) as transactionvalue
from dts 
left join @T t 
  on t.transdate = dts.dt 
 and t.artcode = dts.artcode
order by dts.artcode, dts.dt;

artcode    dt         Qty                   transactionvalue
---------- ---------- --------------------- ---------------------
M100       2010-11-24 0.00                  0.00
M100       2010-11-25 100.00                2900.00
M100       2010-11-26 93.00                 2697.00
M100       2010-11-27 93.00                 2697.00
M100       2010-11-28 93.00                 2697.00
M100       2010-11-29 84.00                 2436.00
M101       2010-11-23 6.00                  179.40
M101       2010-11-24 6.00                  179.40
M101       2010-11-25 106.00                3079.40
M101       2010-11-26 99.00                 2876.40
M101       2010-11-27 99.00                 2876.40
M101       2010-11-28 99.00                 2876.40
M101       2010-11-29 99.00                 2876.40
M101       2010-11-30 90.00                 2615.40

解決此問題的方法是,在一年中的所有天(或所需的時間跨度)內使用CTE,然后適當地left join ,如下所示:

with Calendar as (
    select CAST('2010-01-01' as date) [transdate], 0 [Qty], 0 [transactionvalue]
    union all
    select DATEADD(DAY, 1, [transdate]), 0, 0 from Calendar
    where [transdate] < '2010-12-31'
), with Calendar2 ([artcode], [transdate], [Qty], [transactionvalue]) as (
    select [T].artcode, [C].*  from Calendar [C]
    cross join (select distinct artcode from  MY_TABLE) [T]
)

select [a].[artcode], [a].[transdate], isnull([b].[Qty],[a].[Qty]),isnull([b].[transactionvalue],[a].[transactionvalue]) from Calendar2 [a]
left join MY_TABLE [b] on ([a].transdate = [b].transdate and [a].[artcode] = [b].[artocde])
option(maxrecursion 0)

如果沒有日歷或理貨表格,則可以使用臨時理貨表格

另外,假設由ArdCode分區

;with cte as (
        SELECT 
            TransDate, ArtCode, CumulativeQuantity, CumulativeValue 
        FROM 
            (SELECT
                 ArtCode, 
                 SUM(CAST(REPLACE(REPLACE(NULLIF(Qty, ''), ',', '.'), ' ', '') AS float)) OVER (PARTITION BY artcode ORDER BY transdate) AS CumulativeQuantity,
                 SUM(CAST(REPLACE(REPLACE(NULLIF(TotCostPrice, ''), ',', '.'), ' ', '') AS FLOAT)) OVER (PARTITION BY artcode ORDER BY transdate) AS CumulativeValue,
                 TransDate
             FROM
                 stage_itemhistory 
             WHERE
                 artcode = 'm100' AND stockaffect = 1) S 
        GROUP BY
            TransDate, ArtCode, CumulativeQuantity, CumulativeValue
)
Select TransDate = B.D
      ,A.ArtCode
      ,A.CumulativeQuantity  
      ,A.CumulativeValue
 From ( 
        Select *
              ,NextDate = lead([TransDate],1,dateadd(day,1,[TransDate])) over (partition by ArtCode order by [TransDate]) 
         From  cte
      )  A
 Cross Apply (
                Select Top (DateDiff(DAY,[TransDate],NextDate)) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),[TransDate]) From  master..spt_values n1,master..spt_values n2
             ) B

退貨

TransDate   ArtCode CumulativeQuantity  CumulativeValue
2010-11-24  M100    0                   0
2010-11-25  M100    100                 2900
2010-11-26  M100    93                  2697
2010-11-27  M100    93                  2697
2010-11-28  M100    93                  2697
2010-11-29  M100    84                  2436

我找到了適合我的解決方案:

--Create TempTable
CREATE TABLE #TempTable(
 TransDate Date,
 ArtCode varchar(150),
 CumulativeQuantity float(53),
 CumulativeValue float(53))

--Insert Cumulative data, still missing dates
insert into #TempTable (TransDate, ArtCode, CumulativeQuantity, CumulativeValue)
SELECT TransDate, ArtCode, CumulativeQuantity, CumulativeValue FROM (
        select  ArtCode, 
                SUM(Qty) OVER (partition by artcode order by transdate) AS CumulativeQuantity,
                SUM(TotCostPrice) OVER (partition by artcode order by transdate) AS CumulativeValue,
                TransDate
        from stage_itemhistory where stockaffect=1
        ) S
    group by TransDate, ArtCode, CumulativeQuantity, CumulativeValue;

--Select all with Missing dates with previous dates data
WITH CTE as (
    SELECT TransDate, ArtCode, CumulativeQuantity, CumulativeValue FROM #TempTable
    UNION ALL
    select DATEADD(Day,1,TransDate), ArtCode, CumulativeQuantity, CumulativeValue FROM CTE e
    Where Not Exists (select * from #TempTable e2 where e2.TransDate = DATEADD(DAY,1,e.TransDate) and e.ArtCode=e2.ArtCode)
    and TransDate < GETDATE()
)
select  TransDate, 
        ArtCode,
        CumulativeQuantity,
        ROUND(CumulativeValue,2)
from CTE where TransDate > '2016-01-01'
Order by ArtCode, TransDate
OPTION (MAXRECURSION 0)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM