Daten mit While bis zu einem bestimmten Wert Sumieren und ausgeben

JudAD

Fleissiger Benutzer
Beiträge
71
Hallo,

ich verzweifele gerade an einer Abfrage. Ich habe in einer Tabelle 2 Felder die ich beide ausgeben möchte.

DocNum Quantity
13077970 1
13077971 12
13077980 1
13077981 1
13077982 1
13077983 1
13077984 1
13077985 1
13077986 1
13077987 1
13077988 3
13077989 2
13077990 1

Jetzt möchte ich eine Abfrage generieren, der mir beginnend mit der kleisnten DocNum die Mengen zusammenzählt und nur die Datensätze ausgibt die in Summe einen bestimmten Wert nicht überschreiten.

DECLARE
@i int,
@menge int,
@kdnr int,
@itemcode varchar

set @menge = 20
set @itemcode = 'EP'
set @kdnr = 11048

WHILE (@i < @menge)
BEGIN
select ODLN.DocNum, DLN1.Quantity as Quantity from DLN1
join ODLN on DLN1.DocEntry = ODLN.DocEntry
join OITM on DLN1.ItemCode = OITM.ItemCode
where ODLN.DocDate > '2016-02-01 00:00:00.000' and ODLN.CardCode = @kdnr and DLN1.LineStatus != 'C' and DLN1.ItemCode = @itemcode
set @i = @i + DLN1.Quantity
END

Ausgabe sollte bei obigen Parametern folgende sein:

DocNum Quantity
13077970 1
13077971 12
13077980 1
13077981 1
13077982 1
13077983 1
13077984 1
13077985 1

Irgenwie bekomm ich das nicht hin.

Geht das überhaupt mit While oder benötige ich einen cursor und wenn ja, wie eürde der aussehen.

Danke vorab
 
Werbung:
Habe versehentlich eine Zwischeversion meines Scriptes gepostet.

Unter den set @kdnr.... gehört auch noch: set @i = 0

Der zweite join in der Abfrage ist natürlich in dieser vereinfachten variante nicht notwendig!
 
Hallo,

und hier alles komprimiert auf die notwendigen Felder

ich verzweifele gerade an einer Abfrage. Ich habe in einer Tabelle 2 Felder die ich beide ausgeben möchte.

DocNum Quantity
13077970 1
13077971 12
13077980 1
13077981 1
13077982 1
13077983 1
13077984 1
13077985 1
13077986 1
13077987 1
13077988 3
13077989 2
13077990 1

Jetzt möchte ich eine Abfrage generieren, der mir beginnend mit der kleinsten DocNum die Mengen (Quantity) zusammenzählt und nur die Datensätze ausgibt die in Summe einen bestimmten Wert nicht überschreiten.


DECLARE
@i int,
@menge int

set @menge = 20
set @i = 0

WHILE (@i < @menge)
BEGIN
select DocNum, Quantity from DLN1
set @i = @i + Quantity
END

Ausgabe sollte bei obigen Parametern folgende sein:

DocNum Quantity
13077970 1
13077971 12
13077980 1
13077981 1
13077982 1
13077983 1
13077984 1
13077985 1


Irgenwie bekomm ich das nicht hin.

Geht das überhaupt mit While oder benötige ich einen cursor und wenn ja, wie eürde der aussehen.

Danke vorab
 
Also auch wenn ich das nur bedingt verstehe geht das auf jedenfall sowohl mit WHILE als auch mit CURSOR aber ich würde es mit keinem von beiden machen weil beide Schleifen sind und das weder schnell noch elegant gelöst wäre. Mit MSSQL gibt es da deutlich reizvollere mittel, z.B. mit WITH. Ich bin mir aber nicht sicher ob man die überhaupt braucht.

Um es auf dein reduziertes Beispiel anzuwenden bräuchte es aber irgendwie noch einen Schlüssel nach dem es vorgeht, denn in der Tabelle stehen ja nicht nur die Beispieldatensätze, daher nehme ich jetzt mal die kdnr dazu in der Annahme das die damit zu tun hat:
Code:
SELECT   t.kdnr,
     t.DocNum,
     t.Quantity
FROM   tabelle t
WHERE (   SELECT   sum(tabelle.Quantity)
     FROM   tabelle
     WHERE   tabelle.kdnr = t.kdnr ) <= 20
Das kann man auch mit EXISTS, NOT IN oder als LEFT JOIN auf eine Tabelle:
Code:
SELECT   t1.kdnr,
     t1.DocNum,
     t1.Quantity
FROM   tabelle t1
LEFT JOIN (

SELECT   tabelle.kdnr,
     sum(tabelle.Quantity) AS summe
FROM   tabelle

     ) t2
ON     t1.kdnr = t2.kdnr
WHERE   isnull(t2.summe,0) <= 20
In beiden Beispielen kann kdnr durch mehrere Bedinungen ersetzt werden. Mit IN oder NOT IN ginge das nicht so gut.
 
Hallo & Danke für Deine Hilfe.

Ich habe bereits eine Lösung. Leider habe ich nicht gefunden wie ich das hier zu schließen.

Das oben (while) war nur ein Versuch.

Meine Abfrage Lautet eigentlich (ergibt alle offenen LS-Belege eines bestimmten Kunden mit einem bestimmten Artikel ab einem bestimmten Datum):

select ODLN.DocNum, DLN1.Quantity as Quantity
from DLN1
join ODLN on DLN1.DocEntry = ODLN.DocEntry
where ODLN.DocDate > '2016-02-01 00:00:00.000' and ODLN.CardCode = 11048 and DLN1.LineStatus = 'O' and DLN1.ItemCode = 'EP'
order by ODLN.DocNum

>>Und aus diesem Resultat sollen sollen quasi beginnend mit der kleinsten DocNum nur die Angezeigt werden, die in Summe (Quantity) 20 ergeben.

Und der fachbegriff lautet "Running Total" ;-) - wusste ich nicht.

Ich hatte schon in anderen Foren gelesen und auch mein Problem gepostet - allerdings nur eine mit meiner SQL-Server Version inkompatible Lösung mit SUM(QUANTITY) OVER (ORDER BY...) erhalten. Aber da diese inkompatibel war habe ich weiter gesucht und nach langen herumprobieren schließlich eine Lösung gefunden:

select t5.* from (
select t3.DocNum, t1.OpenQty, SUM(t2.OpenQty) as SUMME
from DLN1 t1, DLN1 t2, ODLN t3, ODLN t4
where t2.DocEntry <= t1.DocEntry and t1.LineStatus = 'O' and t1.ItemCode = 'EP' and t2.LineStatus = 'O' and t2.ItemCode = 'EP'
and t2.DocEntry = t4.DocEntry and t1.DocEntry = t3.DocEntry
and t3.DocDate > '2017-02-01 00:00:00.000' and t3.CardCode = 11048 and t4.DocDate > '2017-02-01 00:00:00.000' and t4.CardCode = 11048
group by t1.ItemCode, t1.LineStatus, t1.OpenQty, t3.DocNum) t5
where t5.SUMME <= 20
union
select top 1 t5.* from (
select t3.DocNum, t1.OpenQty, SUM(t2.OpenQty) as SUMME
from DLN1 t1, DLN1 t2, ODLN t3, ODLN t4
where t2.DocEntry <= t1.DocEntry and t1.LineStatus = 'O' and t1.ItemCode = 'EP' and t2.LineStatus = 'O' and t2.ItemCode = 'EP'
and t2.DocEntry = t4.DocEntry and t1.DocEntry = t3.DocEntry
and t3.DocDate > '2017-02-01 00:00:00.000' and t3.CardCode = 11048 and t4.DocDate > '2017-02-01 00:00:00.000' and t4.CardCode = 11048
group by t1.ItemCode, t1.LineStatus, t1.OpenQty, t3.DocNum) t5
where t5.SUMME >= 20

Gibt es eine einfachere Lösung ??? Mir scheint meine Lösung sehr umständlich - aber ich bin kein SQL-Crack ;-)
 
Ich habe zwei Ansätze gezeigt die eigentlich funktionieren müssten (natürlich brauchst du auch da mehr Code da du ja einige Bedingungen drinne hast die ich nicht so überblicke). Nichts desto trotz könnte es die elegantere Lösung sein nur möchte ich jetzt nicht deinen ganzen Code entstauben, der ist auch nicht grade übersichtlich. Wenn die Lösung läuft überlasse ich es dir sie zu optimieren.
 
Werbung:
Zurück
Oben