计算结算(两个视图的总和,包括过去)

时间:2016-06-29 10:01:37

标签: sql sql-server sql-server-2014

我试图获得每个月剩余的工作单位数,即购买的工作单位数与消耗的工作单位数之和。

我尝试了两种可能性,但两者都有缺陷:

在第一次测试中,我创建了一个“月份”表,其中包含每个月和每年,以便显示我希望使用这些数据创建的最终矩阵中的所有月份。有了这个,只要有一个消耗的工作单位,我得到了收盘,但是当没有时,该列是“空的”,因为它没有得到最后的收盘。

USE OTRS_Revised
SELECT     [Customer], CASE WHEN [Year] < 2016 THEN 1 ELSE [Year] END AS [Year], CASE WHEN [Year] < 2016 THEN 0 ELSE [Month] END AS [Month], [Closing] AS Total, SUM([Closing]) 
                      OVER (PARTITION BY [Customer] ORDER BY [Year], [Month] ROWS UNBOUNDED PRECEDING) AS Closing
FROM         [dbo].[WU_Closing_View]
WHERE [Customer] IN ('CustomerList')
GROUP BY [Customer], [Year], [Month], [Closing]
UNION ALL
SELECT     '' AS Customer, CASE WHEN [Year] < 2016 THEN 1 ELSE [Year] END AS [Year], CASE WHEN [Year] < 2016 THEN 0 ELSE [Month] END AS [Month], '' AS Total, '' AS Sum_bought
FROM         [dbo].Months
WHERE     [Year] <= 2016
GROUP BY Year, Month
ORDER BY Customer, Year, Month

我也试图“逐个月”地进行,并使用以下查询。它工作了一个月,但我找不到任何方法来使用它来获得2016年每个月的结果。

SELECT 
    (SELECT SUM(Closing) AS Expr1
    FROM          OTRS_Revised.dbo.WU_Bought_View
    WHERE      (Customer LIKE 'SomeCustomer') AND (DATEADD(Year, Year - 1900, DATEADD(Month, Month - 1, DATEADD(day, 0, 0))) <= DATEADD(Year, 2016 - 1900, DATEADD(Month, 5 - 1, DATEADD(day, 0, 0))))
    GROUP BY Customer) 

+

(SELECT     SUM(Closing) AS Expr1
FROM          OTRS_Revised.dbo.WU_Consumed_View
WHERE      (Customer LIKE 'SomeCustomer') AND (DATEADD(Year, Year - 1900, DATEADD(Month, Month - 1, DATEADD(day, 0, 0))) <= DATEADD(Year, 2016 - 1900, DATEADD(Month, 5 - 1, DATEADD(day, 0, 0))))
GROUP BY Customer) AS Expr1,
[Month]
FROM OTRS_Revised.dbo.Months
GROUP BY [Month]

2 个答案:

答案 0 :(得分:0)

    SELECT b.* 
    FROM
    ( SELECT     CASE WHEN [Year] < 2016 THEN 1 ELSE [Year] END AS [Year],   CASE WHEN [Year] < 2016 THEN 0 ELSE [Month] END AS [Month]
    FROM         [dbo].Months
    WHERE     [Year] <= 2016
    GROUP BY Year, Month
    ORDER BY Customer, Year, Month ) AS a

LEFT OUTER JOIN
    (SELECT     [Customer], CASE WHEN [Year] < 2016 THEN 1 ELSE [Year] END AS [Year], CASE WHEN [Year] < 2016 THEN 0 ELSE [Month] END AS [Month], [Closing] AS Total, SUM([Closing]) 
                          OVER (PARTITION BY [Customer] ORDER BY [Year], [Month] ROWS UNBOUNDED PRECEDING) AS Closing
    FROM         [dbo].[WU_Closing_View]
    WHERE [Customer] IN ('CustomerList')
    GROUP BY [Customer], [Year], [Month], [Closing]) AS b
    ON a.Month = b.Month )

在您进行联合的方法中,不会删除没有匹配月份的行。由于您还希望没有结束匹配的月份,您需要使用左外连接

答案 1 :(得分:0)

这样的事可能

DECLARE @T TABLE (ID INT,   ProductID INT,  TrDate  DATE,InOut  VARCHAR(10),Amount INT)
INSERT INTO @T VALUES
(1  ,1, '2016-01-01',   'I',    100),
(2  ,2, '2016-01-01',   'I',    100),
(3  ,3, '2016-02-01',   'I',    100),
(4  ,4, '2016-03-01',   'I',    100),
(5  ,1, '2016-03-01',   'I',    100),
(6  ,2, '2016-04-01',   'O',    10),
(7  ,3, '2016-05-01',   'I',    100),
(8  ,5, '2016-05-01',   'I',    100),
(9  ,5, '2016-05-01',   'O',    100),
(10 ,6, '2016-05-01',   'I',    100)

declare @m table (id int, menddate date)
insert  @m values
(1,'2015-12-31'),(2,'2016-01-31'),(3,'2016-02-29'),(4,'2016-03-31'),
(5,'2016-04-30'),(6,'2016-05-31'),(7,'2016-06-30'),(4,'2016-07-31')

Select * 
from
(
select  -- t.*
        x.xproductid , x.xyyyymm,
        SUM(t.total) OVER (partition by x.xproductid
         ORDER BY x.xyyyymm 
          ROWS UNBOUNDED PRECEDING) AS CumulativeTotal
from
(
SELECT t.ProductID tproductid, year(t.trdate) * 100 + month(t.trdate) tyyyymm,
        sum(case when t.Inout = 'I' then t.Amount else t.amount * -1 end) as total      
FROM @T t
group   by  ProductID, year(t.trdate) * 100 + month(t.trdate) 
) t
right outer join
(select distinct productid as xproductid,year(m.menddate) * 100 + month(m.menddate) xyyyymm from @t t, @m m) x on x.xproductid = t.tproductid and x.xyyyymm = t.tyyyymm

) z
where   z.xyyyymm >= 201601
order by z.xProductID,z.xyyyymm

请注意使用右外部联接来获取所有产品的所有月末