Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Wie Update mit max() pro Gruppe (https://www.delphipraxis.net/194211-wie-update-mit-max-pro-gruppe.html)

BlueStarHH 28. Okt 2017 21:14

Datenbank: Firebird • Version: 2.5 • Zugriff über: IBDAC

Wie Update mit max() pro Gruppe
 
Hallo,

ich habe eine Tabelle RechnungPos mit RechnungsNr und PositionsNr. Die PositionsNr gibt die Reihenfolge von Artikeln auf einer Rechnung an. *Einige* Rechnungen enthalten die Postion 999, die per SQL in die nächste freie PositionsNr < 999 geändert werden soll. So soll das aussehen:

Code:
RechnungNr PositionsNr
1           1
1           2
1           999  wird zu 3
2           1
2           2
2           3
2           999  wird zu 4
3           999  wird zu 1
4           1
4           2
Mein Ansatz:
update RechnungPos set PositionsNr max(PositionsNr)+1 where PositionsNr 999
Problem dabei ist max(PositionsNr) wird die 999 zurückgeben und wie kann man das pro RechnungNr setzen/abfragen?

p80286 28. Okt 2017 21:25

AW: Wie Update mit max() pro Gruppe
 
mach einen zusätzlichen Subselect mit
SQL-Code:
where positionsnr<>999
Gruß
K-H

BlueStarHH 28. Okt 2017 21:27

AW: Wie Update mit max() pro Gruppe
 
Zitat:

Zitat von p80286 (Beitrag 1384434)
mach einen zusätzlichen Subselect mit
SQL-Code:
where positionsnr<>999
Gruß
K-H

Danke, aber irgendwie stehe ich gerade auf dem Schlauch. Poste mal bitte den kompletten SQL-Ausdruck.

Aviator 28. Okt 2017 21:57

AW: Wie Update mit max() pro Gruppe
 
Könnte so funktionieren wenn man es wie von p80286 vorgeschlagen mit einem Subselect macht.

SQL-Code:
UPDATE RechnungPos
SET PositionsNr = MAX(SELECT PositionNr FROM RechnungPos WHERE PositionNr <> 999) + 1
WHERE PositionsNr = 999

nahpets 28. Okt 2017 22:17

AW: Wie Update mit max() pro Gruppe
 
Das setzt aber alle PositionsNr, die 999 sind, auf die höchste freie PositionsNr <> 999. Damit käme die 999 nicht mehr vor, aber die (Max <> 999) + 1, genauso oft, wie bisher die 999.
Man müsste die Tabelle satzweise durchgehen und für jeden Satz, dessen PositionsNr = 999 ist, per Update aktuallisieren. Dabei ist Max auf die PositionsNr aber nicht die nächste freie, sondern die höchste vergebene. Lücken kann man damit nicht finden.

'ne Lösung hab' ich nicht, aber eventuell hilft dashier weiter? http://www.delphipraxis.net/85745-da...ds-finden.html

Aviator 28. Okt 2017 22:19

AW: Wie Update mit max() pro Gruppe
 
Zitat:

Zitat von nahpets (Beitrag 1384437)
Das setzt aber alle PositionsNr, die 999 sind, auf die höchste freie PositionsNr <> 999. Damit käme die 999 nicht mehr vor, aber die (Max <> 999) + 1, genauso oft, wie bisher die 999.
Man müsste die Tabelle satzweise durchgehen und für jeden Satz, dessen PositionsNr = 999 ist, per Update aktuallisieren. Dabei ist Max auf die PositionsNr aber nicht die nächste freie, sondern die höchste vergebene. Lücken kann man damit nicht finden.

Das ist richtig. Aber das war ja scheinbar auch die Frage. Zumindest wurde das nicht auf bspw. nur die erste 999er ID eingegrenzt. Mir kommt das zwar auch etwas komisch vor, aber es ist zumindest eine Lösung für die aktuell definierte Frage. :-D

nahpets 28. Okt 2017 22:27

AW: Wie Update mit max() pro Gruppe
 
Ausgehend von der Beispieltabelle, soll je RechnungsNr die kleinste freie PosititionsNr für die 999 vergeben werden.

Ungefähr sowas:

Suche für jede RechnungsNr
jede PositionsNr = 999
und gebe ihr die kleinste freie PositionsNr zu diese RechnungsNr

BlueStarHH 29. Okt 2017 08:00

AW: Wie Update mit max() pro Gruppe
 
Sorry, es war gestern wohl schon zu spät für mich und ich habe einen Teil der Anforderungen verschluckt:

Es soll die nächste "freie" PositionsNr je RechnungNr anstelle der 999 eingetragen werden. Man sieht es an der Beispieltabelle, die ich in der Frage gepostet habe.

TigerLilly 29. Okt 2017 09:22

AW: Wie Update mit max() pro Gruppe
 
UPDATE RechnungPos
SET PositionsNr = (SELECT max(PositionNr)+1 FROM RechnungPos p WHERE PositionNr <> 999 and p.rechnungsnummer=rechnungspos.rechnungsnummer)
WHERE PositionsNr = 999

nahpets 29. Okt 2017 09:52

AW: Wie Update mit max() pro Gruppe
 
Das geht aber schief, wenn es mehr als eine PositionsNr = 999 zu einer RechnungsNr gibt, die bekommen dann alle die Max(PositionNr)+1. Man erhält dann Dubletten, die ggfls. nicht mehr so leicht zu erkennen sind, wie die 999.

Mir fällt momentan keine Lösungsmöglichkeit mit einem einzigen Updatestatement ein. Da muss man wohl mit 'nem Cursor über alle Sätze mit PositionsNr = 999 ran und die einzeln ändern.

Ohne einen eindeutigen Schlüssel für jeden Datensatz, kann man (glaub' ich) die Entstehung von Dubletten nicht vermeiden, sofern die Kombination aus RechnungsNr und PositionsNr = 999 nicht eindeutig ist.

HolgerX 29. Okt 2017 10:12

AW: Wie Update mit max() pro Gruppe
 
Hmm..

Mal eine andere Frage:
Könnten Positionen mit der Nummer 999 nicht stornierte, somit ungültige Rechnungs-Positionen sein?

Deshalb stellt sich hier eher die Frage, ob diese überhaupt gelistet werden oder sowieso keine 'echte' Positionsnummer haben, da storniert.

Ansonsten müsstest Du eine temporäre Tabelle per z.B. Select insert anlegen, dort per die Position anfügen und immer die PosNr neu anhand der letzten Pos aus der Temptable vergeben.

Da diese Temptable immer die höchste PosNr enthält, würde auch der Insert immer die richtige nächste PosNr verwenden.

Zum Schluss würde diese TempTable als Record zurück gegeben werden oder dann als Datenquelle für den Update dienen.

Hab leider kein Beispiel zur Hand.. ;)

BlueStarHH 29. Okt 2017 10:23

AW: Wie Update mit max() pro Gruppe
 
Zitat:

Zitat von nahpets (Beitrag 1384448)
Das geht aber schief, wenn es mehr als eine PositionsNr = 999 zu einer RechnungsNr gibt, die bekommen dann alle die Max(PositionNr)+1. Man erhält dann Dubletten, die ggfls. nicht mehr so leicht zu erkennen sind, wie die 999.

In den Daten hier gibt es die 999 maximal ein mal je RechnungsNr. Insofern lößt der Code von TigerLilly aus Post #9 mein Problem. Danke an alle!

BlueStarHH 29. Okt 2017 10:26

AW: Wie Update mit max() pro Gruppe
 
Zitat:

Zitat von HolgerX (Beitrag 1384450)
Könnten Positionen mit der Nummer 999 nicht stornierte, somit ungültige Rechnungs-Positionen sein?

In den Daten, die ich hier bekommen habe, sind mit 999 Positionen markiert, die immer am Ende stehen sollen. In diesem Fall hat das also nicht mit einem Ungültig-Flag zu tun.

jobo 29. Okt 2017 14:34

AW: Wie Update mit max() pro Gruppe
 
Ist die 999 wirklich immer am Ende der Rechnungspositionsliste?
Und wenn ja und es geht bloß um Sortierung, warum soll sie dann geändert werden, die Sortierung ändert sich dadurch nicht. (außer es sind mehr als 999 Artikel)

BlueStarHH 29. Okt 2017 15:04

AW: Wie Update mit max() pro Gruppe
 
Zitat:

Zitat von jobo (Beitrag 1384464)
Ist die 999 wirklich immer am Ende der Rechnungspositionsliste?

Die 999 gibt an, dass diese Position ans Ende der Liste bei der Ausgabe soll. Wie das intern in der DB sortiert ist, kann man nicht vorhersagen.

Zitat:

Zitat von jobo (Beitrag 1384464)
Und wenn ja und es geht bloß um Sortierung, warum soll sie dann geändert werden, die Sortierung ändert sich dadurch nicht. (außer es sind mehr als 999 Artikel)

Auf der gedrucken Rechnung werden auch die PositionsNr gedruckt. Dort soll keine 999 zu sehen sein sondern stattdessen die nächste freie Nummer. Auf dem Ausdruck ist nach der PositionsNr sortiert.

mkinzler 29. Okt 2017 16:52

AW: Wie Update mit max() pro Gruppe
 
Oder bei der Abfrage

SQL-Code:
select
  <Felder ohne PosNr>,
  iif( PositionNr < 999; PositionNr; SELECT MAX(PositionNr) FROM RechnungPos ps WHERE ps. RechNr = p.RechNr       ps.PositionNr < 999) +1 ) as PositionNr
from
  RechnungPos p
where
  <Bedingung>;


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:19 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz