【问题标题】:SQL Running SubtractionSQL运行减法
【发布时间】:2011-04-30 09:33:28
【问题描述】:

我的结果集如下:

Item    ExpectedQty  ReceivedQty  Short
Item01  30           45           5
Item01  20           45           5

Item02  40           38           2

item03  50           90           10
item03  30           90           10
item03  20           90           10

查询是:

select a.Item, a.ExpectedQty,b.ReceivedQty, b.Short
from a join b on a.Item = b.Item

我需要得到第二张图表中的结果。基本上我每行都有收到的总数量,我需要根据预期数量显示收到的数量,如果有任何短缺我需要在最后一行显示。

预期:

Item    ExpectedQty  ReceivedQty  Short
item01  30           30           0
item01  20           15           5

item02  40           38           2

item03  50           50           0
item03  30           30           0
item03  20           10           10

提前致谢。

已编辑, 第02版;

--    Just a brief of business scenario is table has been created for a good receipt. 
--    So here we have good expected line with PurchaseOrder(PO) in first few line. 
--    And then we receive each expected line physically and that time these 
--    quantity may be different 
--    due to business case like quantity may damage and short quantity like that. 
--    So we maintain a status for that eg: OK, Damage, also we have to calculate
--    short quantity 
--    based on total of expected quantity of each item and total of received line.


if object_id('DEV..Temp','U') is not null
drop table Temp

CREATE TABLE Temp 
(        
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,        
Item VARCHAR(32),
PO VARCHAR(32) NULL,        
ExpectedQty INT NULL,
ReceivedQty INT NULL,
[STATUS] VARCHAR(32) NULL,
BoxName VARCHAR(32) NULL
)


--  Please see first few line with PO data will be the expected lines, 
--  and then rest line will be received line

INSERT INTO TEMP (Item,PO,ExpectedQty,ReceivedQty,[STATUS],BoxName)
SELECT 'ITEM01','PO-01','30',NULL,NULL,NULL UNION ALL 
SELECT 'ITEM01','PO-02','20',NULL,NULL,NULL UNION ALL 
SELECT 'ITEM02','PO-01','40',NULL,NULL,NULL UNION ALL 
SELECT 'ITEM03','PO-01','50',NULL,NULL,NULL UNION ALL 
SELECT 'ITEM03','PO-02','30',NULL,NULL,NULL UNION ALL 
SELECT 'ITEM03','PO-03','20',NULL,NULL,NULL UNION ALL 
SELECT 'ITEM04','PO-01','30',NULL,NULL,NULL UNION ALL 
SELECT 'ITEM01',NULL,NULL,'20','OK','box01' UNION ALL 
SELECT 'ITEM01',NULL,NULL,'25','OK','box02' UNION ALL 
SELECT 'ITEM01',NULL,NULL,'5','DAMAGE','box03' UNION ALL 
SELECT 'ITEM02',NULL,NULL,'38','OK','box04' UNION ALL 
SELECT 'ITEM02',NULL,NULL,'2','DAMAGE','box05' UNION ALL 
SELECT 'ITEM03',NULL,NULL,'30','OK','box06' UNION ALL 
SELECT 'ITEM03',NULL,NULL,'30','OK','box07' UNION ALL 
SELECT 'ITEM03',NULL,NULL,'30','OK','box08' UNION ALL 
SELECT 'ITEM03',NULL,NULL,'10','DAMAGE','box09' UNION ALL
SELECT 'ITEM04',NULL,NULL,'25','OK','box10' 



--  Below Table is my expected result based on above data. 
--  I need to show those data following way. 
--  So I appreciate if you can give me an appropriate query for it. 
--  Note: first row is blank and it is actually my table header. :) 

SELECT  ''as'ITEM', ''as'PO#', ''as'ExpectedQty',''as'ReceivedQty',
''as'DamageQty' ,''as'ShortQty' UNION ALL 

SELECT 'ITEM01','PO-01','30','30','0' ,'0'  UNION ALL 
SELECT 'ITEM01','PO-02','20','15','5' ,'0'  UNION ALL 
SELECT 'ITEM02','PO-01','40','38','2' ,'0'  UNION ALL 
SELECT 'ITEM03','PO-01','50','50','0' ,'0'  UNION ALL 
SELECT 'ITEM03','PO-02','30','30','0' ,'0'  UNION ALL 
SELECT 'ITEM03','PO-03','20','10','10','0' UNION ALL 
SELECT 'ITEM04','PO-01','30','25','0' ,'5'  

【问题讨论】:

  • 您是否意识到您的问题在更新后变得完全不同?您应该将它作为一个新问题发布(如果需要,请参考这个问题)。
  • 是的,我同意了。我已经更新了另一个线程。如果你有时间,请通过它。 stackoverflow.com/questions/5866913/sql-running-subtraction

标签: sql tsql sql-server-2000


【解决方案1】:

问题的一部分是获得预期项目数量的运行总数。为此,您需要一种方法来区分具有相同项目的行,以及一个用于排放相同项目数量的顺序的规则。

为了尝试解决您的问题,我将假设有一个时间戳列,其值提供放电顺序并且在同一项目组中是唯一的。

这是我测试我的解决方案的示例数据定义:

CREATE TABLE TableA (Item varchar(50), ExpectedQty int, Timestamp int);
INSERT INTO TableA
SELECT 'Item01', 30, 1 UNION ALL
SELECT 'Item01', 20, 2 UNION ALL
SELECT 'Item02', 40, 1 UNION ALL
SELECT 'item03', 50, 1 UNION ALL
SELECT 'item03', 30, 2 UNION ALL
SELECT 'item03', 20, 3;

CREATE TABLE TableB (Item varchar(50), ReceivedQty int);
INSERT INTO TableB
SELECT 'Item01', 45 UNION ALL
SELECT 'Item02', 38 UNION ALL
SELECT 'item03', 90;

这是我的解决方案:

SELECT
  Item,
  ExpectedQty,
  ReceivedQty = CASE
    WHEN RemainderQty >= 0 THEN ExpectedQty
    WHEN RemainderQty < -ExpectedQty THEN 0
    ELSE RemainderQty + ExpectedQty
  END,
  Short = CASE
    WHEN RemainderQty >= 0 THEN 0
    WHEN RemainderQty < -ExpectedQty THEN ExpectedQty
    ELSE ABS(RemainderQty)
  END
FROM (
  SELECT
    a.Item,
    a.ExpectedQty,
    RemainderQty = b.ReceivedQty - a.RunningTotalQty
  FROM (
    SELECT
      a.Item,
      a.Timestamp,
      a.ExpectedQty,
      RunningTotalQty = SUM(a2.ExpectedQty)
    FROM TableA a
      INNER JOIN TableA a AS a2 ON a.Item = a2.Item AND a.Timestamp >= a2.Timestamp
    GROUP BY
      a.Item,
      a.Timestamp,
      a.ExpectedQty
  ) a
    INNER JOIN TableB b ON a.Item = b.Item
) s

【讨论】:

  • 优秀的 Andriy M,太棒了。
  • 请看我上面编辑的问题。我已经更改了表结构,并且查询应该适用于同一项目的多个接收行。
  • 有时更改的问题需要对已接受的答案进行非常小的更改。对不起,但你的情况并非如此。如果您发现在没有帮助的情况下很难更改我的解决方案以符合您的新要求,请发布一个新问题。陈述您的问题,发布您已经获得的解决方案并指定它的限制。这样一来,事情就不会像人们无休止地编辑他们的问题和答案时那样变得混乱。
【解决方案2】:
select a.Item, a.ExpectedQty,b.ReceivedQty, (a.ExpectedQty - b.ReceivedQty) as 'Short' from a join b on a.Item = b.Item

【讨论】:

    【解决方案3】:
    SELECT  a.ExpectedQty,
        b.ReceivedQty,
        CASE WHEN b.ReceivedQty < a.ExpectedQty
             THEN b.ReceivedQty - a.ExpectedQty
             ELSE 0
        END Short
    FROM    dbo.a a
    INNER JOIN dbo.b b
    ON      a.ItemId = b.ItemId
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-01
      相关资源
      最近更新 更多