如何在sql中执行多行计算

时间:2014-12-23 09:21:06

标签: sql-server

我有4个结果集,我将其移动到一个临时表中以用于报告目的:

Date        Issued_Id   Item_Name   Qty_Issued  Qty_Return  Qty_Damage  Type    Balance OPBal
----------------------------------------------------------------------------------------------
Dec 18 2014 6003        Bed Covers  4           0           0           IS      NULL    245
Dec 18 2014 6008        Bed Covers  4           0           0           IS      NULL    245
2014-12-17  6000        Bed Covers  0           22          0           RT      NULL    245
2014-12-22  7002        Bed Covers  0           10          0           RT      NULL    245

现在我必须在(OPBal=Qty_Issued + OPBal)时添加Type="IS",在(OPBal=Qty_Return - OPBal)时减去type="RT"

它应该像这样打印

Date        Issued_Id   Item_Name   Qty_Issued  Qty_Return  Qty_Damage  Type    Balance OPBal
---------------------------------------------------------------------------------------------
Dec 18 2014 6003        Bed Covers  4           0           0           IS      NULL    249
Dec 18 2014 6008        Bed Covers  4           0           0           IS      NULL    253
2014-12-17  6000        Bed Covers  0           22          0           RT      NULL    231
2014-12-22  7002        Bed Covers  0           10          0           RT      NULL    221

如何在SQL Server中使用游标?

5 个答案:

答案 0 :(得分:1)

目前还不清楚问题中四行的排序标准是什么 - 既不是按日期也不是Issued_Id。我将假设条目应该由Issued_Id订购,并且您的示例是错误的。

获得累积总和的最简单方法是使用window query

SELECT Date, Issued_Id, Item_Name, Qty_Issued, Qty_Return, Qty_Damage, Type, Balance
     , SUM(
           CASE WHEN Type='IS' THEN Qty_Issued
                WHEN Type='RT' THEN -Qty_Return
           END
       ) OVER (
           ORDER BY Issued_Id ROWS UNBOUNDED PRECEDING
       ) + OPBal AS OPBal
    FROM #Temp1
    ORDER BY Issued_Id;

甚至可以通过完全忽略Type列和CASE表达式来简化它。

SELECT Date, Issued_Id, Item_Name, Qty_Issued, Qty_Return, Qty_Damage, Type, Balance
     , SUM(Qty_Issued - Qty_Return)
       OVER (ORDER BY Issued_Id ROWS UNBOUNDED PRECEDING) + OPBal AS OPBal
    FROM #Temp1
    ORDER BY Issued_Id;

上述查询的设置:

CREATE TABLE #Temp1
( Date DATE NOT NULL
, Issued_Id INTEGER NOT NULL
, Item_Name VARCHAR(32) NOT NULL
, Qty_Issued DECIMAL NOT NULL DEFAULT 0
, Qty_Return DECIMAL NOT NULL DEFAULT 0
, Qty_Damage DECIMAL NOT NULL DEFAult 0
, Type VARCHAR(2) NOT NULL
, Balance DECIMAL
, OPBal DECIMAL NOT NULL
);

INSERT INTO #Temp1 VALUES
('2014-12-18', 6003, 'Bed Covers', 4, 0,  0, 'IS', NULL, 245),
('2014-12-18', 6008, 'Bed Covers', 4, 0,  0, 'IS', NULL, 245),
('2014-12-17', 6000, 'Bed Covers', 0, 22, 0, 'RT', NULL, 245),
('2014-12-22', 7002, 'Bed Covers', 0, 10, 0, 'RT', NULL, 245);

答案 1 :(得分:0)

试试这个

SELECT [Date],
       Issued_ID,
       Item_Name,
       Qty_Issued,
       Qty_Return,
       Qty_Damage,
       [Type],
       Balance,
       OPBal= CASE
                WHEN TYPE = 'IS' THEN Qty_Issued + OPBal
                WHEN TYPE = 'RT' THEN Qty_Return - OPBal
                ELSE 0
              END
FROM   #TEMP

答案 2 :(得分:0)

目前尚不清楚您的记录是由哪些人订购的。它似乎是Date(最早的第一个)和Issue_Id(最小的第一个)。如果我错了,只需根据您的意愿通过以下声明中的条款更改顺序。

你正在寻找的是一种运行总计,有条件的Qty_Issued和Qty_Return得到总结。通过使用带有窗口子句的SUM的分析使用,您可以实现这一点。

SELECT [Date], Issued_Id, Item_Name, Qty_Issued, Qty_Return, Qty_Damage, Type, Balance,
  OPBal 
  + SUM(case when type = 'IS' then Qty_Issued else 0 end) OVER (ORDER BY [Date] desc, issue_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
  - SUM(case when type = 'RT' then Qty_Return else 0 end) OVER (ORDER BY [Date] desc, issue_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
  AS OPBal
FROM mytable
ORDER BY [Date] desc, issue_id;

由于Qty_Issued和Qty_Return数据中的零值不合适,您可能还可以使用:

SELECT [Date], Issued_Id, Item_Name, Qty_Issued, Qty_Return, Qty_Damage, Type, Balance,
  OPBal 
  + SUM(Qty_Issued - Qty_Return) OVER (ORDER BY [Date] desc, issue_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
  AS OPBal
FROM mytable
ORDER BY [Date] desc, issue_id;

答案 3 :(得分:0)

CREATE TABLE #TT
(
    [Date] DateTime,
    Issued_Id VARCHAR(100),
    Item_Name VARCHAR(100),
    Qty_Issued INT,
    Qty_Return INT,
    Qty_Damage INT,
    [Type] VARCHAR(100),
    Balance INT,
    OPBal INT
)

INSERT INTO  #TT
SELECT 'Dec 18 2014', 6003,' Bed Covers ', 4,0,0,'IS', NULL,245 UNION ALL
SELECT 'Dec 18 2014', 6008,' Bed Covers ', 4,0,0,'IS',  NULL,245 UNION ALL
SELECT '2014-12-17', 6000,' Bed Covers ', 4,22,0,'RT', NULL, 245 UNION ALL
SELECT '2014-12-22',  7002,' Bed Covers ', 4,10,0,'RT',  NULL,245 

--- IF you want to  apply this logic with out any sort(as shown in your question)
     SELECT [Date],Issued_Id, Item_Name, Qty_Issued, Qty_Return, Qty_Damage, Type, Balance,
  OPBal 
  + SUM(case when type = 'IS' then Qty_Issued else 0 end) OVER (ORDER BY (SELECT 1) ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
  - SUM(case when type = 'RT' then Qty_Return else 0 end) OVER (ORDER BY (SELECT 1) ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
  AS OPBal
FROM #TT 


--- IF you want to order records by [Date] & issued_id then apply this logic
     SELECT [Date],Issued_Id, Item_Name, Qty_Issued, Qty_Return, Qty_Damage, Type, Balance,
  OPBal 
  + SUM(case when type = 'IS' then Qty_Issued else 0 end) OVER (ORDER BY [Date] ASC, issued_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
  - SUM(case when type = 'RT' then Qty_Return else 0 end) OVER (ORDER BY [Date] ASC, issued_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
  AS OPBal
  ,SUM(case when type = 'IS' then Qty_Issued else 0 end) OVER (ORDER BY [Date] ASC, issued_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
  ,SUM(case when type = 'RT' then Qty_Return else 0 end) OVER (ORDER BY [Date] ASC, issued_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
FROM #TT 

答案 4 :(得分:0)

感谢大家.. 我用光标和案例得到了解决方案......

DECLARE db_cursor CURSOR for select id from #Temp1;
open db_cursor
fetch next from db_cursor into @varData
while @@FETCH_STATUS=0
begin
set @LastAmt =  ( select OPBal= case 
when Type='IS' then @LastAmt+Qty_Issued
when type='RT' then @LastAmt-(Qty_Return+Qty_Damage) 
when type='OP' then OPBal
else 0
end
from #Temp1 where id = @varData)
update #Temp1 set OPBal= @LastAmt where id = @varData
FETCH NEXT
FROM db_cursor INTO @varData
END
CLOSE db_cursor
DEALLOCATE db_cursor
select * from #Temp1