2017-08-16 1 views
1

Ich habe eine vorhandene gespeicherte Prozedur, die Einkaufswagen Artikel als einzelne Zeilen zurückgibt, mit einem der Felder ist der genannten Artikel.Nur bis zu einer maximalen Anzahl einfügen?

Im Falle eines Werbeangebots, zum Beispiel kaufen 2 und erhalten noch 2 kostenlos, dann wird das gleiche Produkt als zwei Zeilen zurückgegeben, mit einem separaten Preis und einer Menge für jeden. In diesem Fall 2 Zeilen mit einer Anzahl von 2 in jeder Zeile.

Die Prozedur prüft dann jede Zeile mit der Menge auf Lager und ändert die Zeile, falls erforderlich, durch Einfügen in eine neue Tabelle für die aktualisierte Bestellung. Normalerweise befinden sich viele Artikel für jedes Produkt auf einmal, aber in seltenen Situationen (normalerweise für Endlaufprodukte) können weniger Artikel auf Lager sein, als der Warenkorb insgesamt zulassen sollte.

In diesem Beispiel sagen wir, es gibt 3 übrig. Das Verfahren würde jede Reihe als normal vergleichen und sehen, dass es 3 auf Lager gibt und die Reihe nur nach 2 sucht. So besteht jede Reihe die Prüfung, obwohl wir eine kurze sind.

Das Problem, das ich habe, ist, wie kann ich eine laufende Summe von wie viel Elemente sind in den Warenkorb, wenn jede Reihe einzeln verglichen wird? Kann ich für jede Einfügung einen int-Wert deklarieren und aktualisieren?

bearbeiten Beispieldaten Problem zu veranschaulichen:

sagen können, die Auftragsnummer 1 kehrt das gleiche Produkt auf 3 Reihen. Die volle Preis, günstige und frei (wahrscheinlich keine realistische Situation, aber eine, die mein Chef will mir sowieso berücksichtigen)

LineID | ProductID | Price | Quantity | Note 
001  | 00001 | 100 | 2  | 
002  | 00001 | 50 | 2  | 
003  | 00001 |  0 | 2  | 

Diese Zeilen in einer temporären Tabelle sind item, die zu den Produkten products Tabelle von ProductID verbunden ist die wie folgt aussehen würde:

ProductID | BasePrice | QuantityAvailable 
00001  |  100 |  3 

Dann werden die Produkte mit dieser Abfrage geprüft werden:

UPDATE item 
     SET 
      note = 
       CASE WHEN product.quantityAvailable <= 0 THEN 'This item is no longer available' 
        WHEN item.quantity > product.quantityAvailable THEN 'Not Enough Stock' 
        WHEN product.quantityAvailable > item.Quantity THEN REPLACE(note, 'Not Enough Stock', '') 
        ELSE 'Not Enough Stock' END 
      , quantity = 
       CASE WHEN product.quantityAvailable < item.Quantity THEN product.quantityAvailable 
        ELSE item.Quantity END 
     OUTPUT inserted.ID, deleted.note, inserted.note, deleted.quantity, inserted.quantity, 
     INTO @modifiedItems 
     FROM item 
     INNER JOIN product ON product.ProductID = item.ID 

Das Endziel ist für die Positionstabelle die maximale Anzahl verfügbar in allen Reihen, mit dem Ergebnis, entsprechend aktualisiert werden:

LineID | ProductID | Price | Quantity | Note 
001  | 00001 | 100 | 2  | 
002  | 00001 | 50 | 1  | Not enough stock 
003  | 00001 |  0 | 0  | Not enough stock 

bearbeiten 2: Electric Boogaloo

habe ich versucht, zu verwenden, eine lokale Variable, um eine laufende Summe zu berechnen, aber diese scheint direkt auf den Gesamtwert zu springen. Beispiel unten:

DECLARE @runningTotalQuantity int = 0 
UPDATE item 
     SET 
      note = 
       CASE WHEN product.quantityAvailable <= 0 THEN 'This item is no longer available' 
        WHEN item.quantity > product.quantityAvailable THEN 'Not Enough Stock' 
        WHEN product.quantityAvailable > item.Quantity THEN REPLACE(note, 'Not Enough Stock', '') 
        ELSE 'Not Enough Stock' END 
      , quantity = 
       CASE WHEN @runningTotalQuantity != 0 AND @runningTotalQuantity <= ItemLimits.limitedQty AND (@runningTotalQuantity + Item.Quantity) <= ItemLimits.limitedQty then Item.Quantity 
        WHEN (@runningTotalQuantity + Item.quantity) >= ItemLimits.limitedQty THEN (ItemLimits.limitedQty - @runningTotalQuantity) WHEN product.quantityAvailable < item.Quantity THEN product.quantityAvailable 
        ELSE item.Quantity END 
      , @runningTotalQuantity = @runningTotalQuantity + item.Quantity 

     OUTPUT inserted.ID, deleted.note, inserted.note, deleted.quantity, inserted.quantity, 
     INTO @modifiedItems 
     FROM item 
     INNER JOIN product ON product.ProductID = item.ID 

Aber dies folgendes Ergebnis hat:

LineID | ProductID | Price | Quantity | Note 
001  | 00001 | 100 | 2  | 
002  | 00001 | 50 | 6  | 
003  | 00001 |  0 | 6  | 
+0

Es anderen helfen könnte Ihre Frage, ob yo zu verstehen Sie enthalten einige Beispieldaten, die das Problem veranschaulichen. –

Antwort

0

Werfen Sie einen Blick auf die unten Abfrage, kann es helfen Sie

update item set note = case when precedingSum> t.QuantityAvailable then 'Not Enough Stock' Else '' End 
    from 
    (
    select item.*,Product.QuantityAvailable,sum(Quantity) over(partition by item.ProductId order by item.LineId rows UNBounded Preceding)precedingSum 
    from Item inner join Product on item.ProductId=Product.ProductId 
    ) t where t.LineId = Item.LineId 
1

Es ist leicht, insgesamt laufen zu berechnen Verwenden Sie in SQL Server 2014 einfach SUM() OVER (...). Die Reihenfolge der Ergebnisse ist wichtig für die laufende Summe. Ich habe LineID verwendet, um die Zeilen zu sortieren. Sie können eine andere Bestellung wählen, die zu Ihnen passt.

Der erste CTE in der Abfrage unten berechnet die laufende Summe für jedes Produkt und die Differenz DiffQuantity sagt uns, in welcher Zeile das Produkt erschöpft ist.

Der neue Wert von Quantity ist eine der folgenden drei Möglichkeiten: 1) Wenn noch genügend Bestand vorhanden ist, ändert sich die nicht. 2) Wenn es überhaupt keinen Bestand gibt, ist Null. 3) Es kann eine Reihe dazwischen geben, in der teilweise abnimmt.

Abschließend wird die Quelltabelle mit den neuen Werten und Notes aktualisiert.

Führen Sie diese Abfrage CTE-by-CTE und untersuchen Sie Zwischenergebnisse, um zu verstehen, wie es funktioniert.

Beispieldaten

DECLARE @Items TABLE (LineID int PRIMARY KEY, ProductID int, Price money, Quantity int, Note nvarchar(4000)); 

INSERT INTO @Items (LineID, ProductID, Price, Quantity, Note) VALUES 
(001, 00001, 100, 2, ''), 
(002, 00001, 50, 2, ''), 
(003, 00001, 0, 2, ''); 

DECLARE @Products TABLE (ProductID int PRIMARY KEY, BasePrice money, QuantityAvailable int); 
INSERT INTO @Products (ProductID, BasePrice, QuantityAvailable) VALUES 
(00001, 100, 3); 

Abfrage

WITH 
CTE 
AS 
(
    SELECT 
     I.LineID 
     ,I.ProductID 
     ,I.Price 
     ,I.Quantity 
     ,I.Note 
     ,P.QuantityAvailable 
     ,SUM(I.Quantity) OVER (PARTITION BY I.ProductID ORDER BY I.LineID 
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS SumQuantity 
     ,SUM(I.Quantity) OVER (PARTITION BY I.ProductID ORDER BY I.LineID 
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
     - P.QuantityAvailable AS DiffQuantity 
    FROM 
     @Items AS I 
     INNER JOIN @Products AS P ON P.ProductID = I.ProductID 
) 
,CTE2 
AS 
(
    SELECT 
     LineID 
     ,ProductID 
     ,Price 
     ,Quantity 
     ,Note 
     ,QuantityAvailable 
     ,DiffQuantity 
     ,CASE WHEN DiffQuantity > 0 THEN 'Not enough stock' ELSE '' END AS NewNote 

     ,CASE WHEN DiffQuantity > 0 
     THEN 
      CASE WHEN Quantity > DiffQuantity 
      THEN DiffQuantity 
      ELSE 0 END 
     ELSE Quantity END AS NewQuantity 
    FROM CTE 
) 
UPDATE CTE2 
SET 
    Quantity = NewQuantity 
    ,Note = NewNote 
; 

Ergebnis

SELECT * FROM @Items; 

+--------+-----------+--------+----------+------------------+ 
| LineID | ProductID | Price | Quantity |  Note  | 
+--------+-----------+--------+----------+------------------+ 
|  1 |   1 | 100.00 |  2 |     | 
|  2 |   1 | 50.00 |  1 | Not enough stock | 
|  3 |   1 | 0.00 |  0 | Not enough stock | 
+--------+-----------+--------+----------+------------------+ 
Verwandte Themen