0

重複の可能性:
SQL での負の値の処理

製品の将来の在庫の日付と数量をリストするデータ セットがあります。時折、需要が将来の供給を上回り、将来の数量がマイナスになることがあります。その将来の負の数量を以前の供給に織り込む必要があるので、供給を過剰販売して問題を悪化させません。

次のデータセットでは、10-19 の需要に備えて、プラスの数量が残るまでチェーンの上流にマイナスの数量を適用する必要があります。

"ID","SKU","DATE","QUANTITY"
"1","001","2012-06-22","1656"
"2","001","2012-07-13","1986"
"3","001","2012-07-27","-283"
"4","001","2012-08-17","2718"
"5","001","2012-08-31","-4019"
"6","001","2012-09-14","7212"
"7","001","2012-09-21","782"
"8","001","2012-09-28","2073"
"9","001","2012-10-12","1842"
"10","001","2012-10-19","-12159"

私はこれにそれを取得する必要があります:

"ID","SKU","DATE","QUANTITY"
"1","001","2012-06-22","1656"
"2","001","2012-07-13","152"

while ループと外部適用の使用を検討しましたが、まだこれを行う方法が見つからないようです。どんな助けでも大歓迎です。これは、SQL Server 2008 R2 で機能する必要があります。

別の例を次に示します。

"1","002","2012-07-13","1980"
"2","002","2012-08-10","-306"
"3","002","2012-09-07","826"

次のようになります。

"1","002","2012-07-13","1674"
"3","002","2012-09-07","826"

基本的に、私がする必要があるのは、負の値を持つ最も遠い日付から始めて、最初の正の値になるまで戻ることです。次に、次の最も遠い日付に戻り、再び正の値になるまで作業を進めます。最初の例では、-12,159 から始めて 2 行目までさかのぼり、最終的に正の値が得られます。例 2、-306 は 1980 年までさかのぼって 1674 を返します。

4

2 に答える 2

4

2 つの外側の適用を使用する必要があります。数量が負の最大日付を最初に取得します (これはウィンドウ関数を使用して行うこともできますが、後で参照するためにサブクエリまたは共通テーブル式に含める必要があります)。次の外側の適用では、現在の行と最後の負の行の間のすべての数量を合計できます。

SELECT  ID, 
        SKU, 
        Date, 
        CASE WHEN Quantity2 < Quantity THEN Quantity2 ELSE Quantity END [Quantity]
FROM    T
        OUTER APPLY
        (   SELECT  MAX(Date) [LastNegativeDate]
            FROM    T T1
            WHERE   T1.SKU = T.SKU
            AND     Quantity < 0
        ) LastNegative
        OUTER APPLY
        (   SELECT  SUM(Quantity) [Quantity2]
            FROM    T T2
            WHERE   T2.SKU = T.SKU
            AND     T2.Date BETWEEN T.Date AND LastNegativeDate
        ) Quantity
WHERE   CASE WHEN Quantity2 < Quantity THEN Quantity2 ELSE Quantity END > 0
ORDER BY SKU, Date

これは、指定した両方の例で機能します: http://sqlfiddle.com/#!3/ad650/2

ID  SKU     DATE                QUANTITY
1   001     June, 22 2012       1656
2   001     July, 13 2012       152
11  002     July, 13 2012       1674
13  002     September, 07 2012  826
于 2012-06-14T16:31:55.780 に答える
1

SPROC アプローチが必要な場合は、こちらをご覧ください。これは、これまでのすべてのシナリオで機能しました。使用したデータは次のとおりです。

--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(1,'001',1656)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(2,'001',1986)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(3,'001',-283)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(4,'001',2718)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(5,'001',-4019)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(6,'001',7212)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(7,'001',782)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(8,'001',2073)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(9,'001',1842)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(10,'001',-12159)

--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(1,'002',1980)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(2,'002',-306)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(3,'002',826)

--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(1,'003',2592)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(2,'003',2592)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(3,'003',2448)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(4,'003',-4836)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(5,'003',1968)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(6,'003',1074)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(7,'003',324)
--INSERT INTO TestQuantity(ID, SKU, Quantity) Values(8,'003',1638)

SQLは次のとおりです。

CREATE TABLE #Results(ID int, SKU varchar(50), Quantity int)

DECLARE @sku as VARCHAR(50)
DECLARE skuCursor CURSOR FOR
    SELECT DISTINCT SKU FROM TestQuantity WHERE Quantity < 0

OPEN skuCursor
FETCH NEXT FROM skuCursor INTO @sku

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @id AS INT
    DECLARE @quantity AS INT
    DECLARE quantityCursor CURSOR FOR
        SELECT ID, Quantity FROM TestQuantity WHERE SKU=@sku AND ID <= (SELECT MAX(ID) FROM TestQuantity WHERE SKU=@sku and Quantity < 0) ORDER BY ID DESC

    OPEN quantityCursor

    FETCH NEXT FROM quantityCursor
    INTO @id, @quantity

    DECLARE @firstID AS INT = @id
    DECLARE @sum AS INT = -1
    DECLARE @currentID AS INT
    DECLARE @currentQuantity AS INT
    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF @sum < 0
        BEGIN
            SELECT @currentID = ID, @currentQuantity = Quantity FROM TestQuantity WHERE SKU=@sku AND ID=@id - 1
            SET @sum = @currentQuantity + @quantity

            WHILE(@sum < 0)
            BEGIN
                SELECT @currentID = ID, @currentQuantity = Quantity FROM TestQuantity WHERE SKU=@sku AND ID=@currentID - 1
                SET @sum = @currentQuantity + @sum  
            END 
        END
        FETCH NEXT FROM quantityCursor
        INTO @id, @quantity 
    END

    INSERT INTO #results(ID, SKU, Quantity)
        SELECT ID, SKU, QUANTITY FROM TestQuantity WHERE ID > @firstID and SKU=@sku
    INSERT INTO #results(ID, SKU, Quantity)
        SELECT ID, SKU, QUANTITY FROM TestQuantity WHERE ID < @currentID and SKU=@sku
    INSERT INTO #results(ID, SKU, Quantity)
        SELECT @currentID, @sku, @sum

    CLOSE quantityCursor
    DEALLOCATE quantityCursor

    FETCH NEXT FROM skuCursor INTO @sku 
END 

CLOSE skuCursor
DEALLOCATE skuCursor

SELECT * FROM #results order by sku, id

DROP TABLE #results

私の結果:

1   001 1656
2   001 152
1   002 1674
3   002 826
1   003 2592
2   003 204
5   003 1968
6   003 1074
7   003 324
8   003 1638
于 2012-06-14T16:48:35.010 に答える