SQL Abfrage mit Subselect

ORA_SQL

Neuer Benutzer
Beiträge
2
Hallo zusammen,

ich sitze an einer (für mich) kniffligen Aufgabe: ich habe 1 Tabelle ORDERS mit Bestellungen, deren Primärschlüssel das Feld ORDERNR ist.

Nun gibt es fachlich die Möglichkeit mehrere Einzelbestellungen zu einer Gesamtbestellung zusammenzufassen, sodass in derselben Tabelle ein weiterer Eintrag mit neuer ORDERNR angelegt wird. In einer weiteren Spalte ORDERS_FROM werden dabei die beteiligten ORDERNR der Originalbestellungen kommasepariert eingetragen, bspw." [ORDERS] 4711, 4712, 5001".
Da die Logik des Programms nur noch auf dem Datensatz der zusammengefassten Gesamtbestellung arbeitet, möchte ich sich ändernde Attribute auch an den Einzelbestellungen vermerken.
Ich hatte mir dazu folgendes überlegt:
Ich lege eine neue Tabelle TAB_TEMP an, in die ich zunächst die ORDERNR der Einzelbestellungen als Primärschlüssel hinterlege, die zu einer Gesamtbestellung zusammengefasst worden sind (die bekomme ich über ein gesetztes Flag bei der Einzelbestellung raus).
Jetzt würde ich am liebsten so etwas sagen wie "nimm aus der Tabelle TAB_TEMP Zeile für Zeile die jeweilige TAB_TEMP.ORDERNR und liefere die ORDERS.ORDERNR zurück, die TAB_TEMP.ORDERNR enthält, quasi
...
WHERE ORDERS_FROM LIKE ('%'|| (SELECT ORDERNR FROM TAB_TEMP)||'%')
...

und füge die ORDERS.ORDERNR der Gesamtbestellung in das Feld TAB_TEMP.ORDERS_TOTAL in der Zeile mit der ORDERNR der Einzelbestellung ein.

Das funktioniert aber leider nicht, da das SUBSELECT mehr als 1 Eintrag zurückliefert.

Beispiel:

Tabelle ORDERS Auszug:

ORDERNR|ORDERS_FROM|PAID|SUB_ORDER|...
4711|NULL|0|1|...
4712|NULL|0|1|...
5001|NULL|0|1|...
6001|NULL|0|0|...
6002|NULL|0|1|...
6003|NULL|0|1|...
8003|[ORDERS]4711,4712,5001|1|0|...
9000|[ORDERS]6002,6003|1|0|...

Ziel
Tabelle TAB_TEMP (Auszug):

ORDERNR|ORDERS_TOTAL|PAID_TOTAL|
4711|8003|1|...
4712|8003|1|...
5001|8003|1|...
6002|9000|1|...
6003|9000|1|...

Anschließend möchte ich bei den Einzelbestellungen den Wert PAID gemäß der Gesamtbestellung setzen. Kann mir jemand Tipps geben?
 
Werbung:
wenn ich dich richtig verstehe, hast Du:

Code:
test=# select * from orders ;
 ordernr |  orders  | paid
---------+----------------+------
  4711 |  | f
  4712 |  | f
  5001 |  | f
  6001 |  | f
  6002 |  | f
  6003 |  | f
  8003 | 4711,4712,5001 | t
  9000 | 6002,6003  | t
(8 Zeilen)

in folgenden ordernr soll das Feld paid auf true gesetzt werden:

Code:
test=*# select order_nr from (select ordernr, regexp_split_to_table(orders,',')::int as order_nr, paid from orders where orders is not null) x;
 order_nr
----------
  4711
  4712
  5001
  6002
  6003
(5 Zeilen)

dann machen wir das einfach:

Code:
test=# update orders set paid = true where ordernr in (select order_nr from (select ordernr, regexp_split_to_table(orders,',')::int as order_nr, paid from orders where orders is not null) foo) ;
UPDATE 5
test=*# select * from orders ;
 ordernr |  orders  | paid
---------+----------------+------
  6001 |  | f
  8003 | 4711,4712,5001 | t
  9000 | 6002,6003  | t
  4711 |  | t
  4712 |  | t
  5001 |  | t
  6002 |  | t
  6003 |  | t
(8 Zeilen)

Das ist kein Oraggle, sondern PostgreSQL. Vielleicht kann Ora das aber auch - ich weiß es nicht. Dein Tabellendesign ist übrigens, ähm, nicht schön.
 
Hallo akretschmer,

Vielen Dank für den Tipp, probiere ich aus. Was aber dabei nicht berücksichtigt wird, ist das hier der Wert für PAID einfach auf true gesetzt wird (hatte ich aber auch nicht so aufgeführt). Der Wert muss aus der Gesamtorder übernommen werden, da ich bspw. auch das Datum der Bezahlung und weitere Felder übernehmen möchte, d.h. individuelle gesetzte Werte bei der Gesamtorder.
Die DB-Struktur stammt nicht von mir, sondern existiert so schon.
 
ok, ich hab mal noch ein Feld paid2 angehangen, mit INT-Werten:

Code:
test=*# select * from orders ;
 ordernr |  orders  | paid | paid2
---------+----------------+------+-------
  4711 |  | f  |  92
  4712 |  | f  |  15
  5001 |  | f  |  43
  6001 |  | f  |  17
  6002 |  | f  |  45
  6003 |  | f  |  25
  8003 | 4711,4712,5001 | t  |  69
  9000 | 6002,6003  | t  |  8
(8 Zeilen)

Ich update das jetzt und setze dort, wo mehrere Rechnungen sind, die einzelnen Rechnungen auf die Summer aller enthaltenen.

Code:
test=*# update orders set paid2=foo.sum from (select order_nr, sum(orders.paid2) over (partition by x.ordernr) from (select ordernr, regexp_split_to_table(orders,',')::int as order_nr, paid2 from orders ) x left join orders on x.order_nr=orders.ordernr) foo where foo.order_nr=ordernr;
UPDATE 5
test=*# select * from orders ;
 ordernr |  orders  | paid | paid2
---------+----------------+------+-------
  6001 |  | f  |  17
  8003 | 4711,4712,5001 | t  |  69
  9000 | 6002,6003  | t  |  8
  4711 |  | f  |  150
  4712 |  | f  |  150
  5001 |  | f  |  150
  6002 |  | f  |  70
  6003 |  | f  |  70
(8 Zeilen)

Wenn Du stattdessen die einzelnen auf den Wert der zusammengefaßten setzen willst, so ist das nur eine marginale Änderung - das schaffst du.
 
Werbung:
Wenn ich das richtig verstanden habe, möchtest Du die Werte der Spalten einer Bestellliste (also ein Eintrag mit SUB_ORDER=1) in die zugehörigen Einzelbestellungen kopieren?
In dem Fall brauchst aber keine Zwischentabelle:
update orders a set (a.paydate,a.paid)=
(
select c.paydate,c.paid from(
select b.ordernr,b.paydate,b.paid,b.order_content from(
select distinct ordernr,paydate,paid,
regexp_substr(replace(orders_from,'[ORDERS]',NULL),'[^,]+', 1, level) as order_content
from orders
where sub_orders=0
and ORDERS_FROM is not null
connect by regexp_substr(replace(orders_from,'[ORDERS]',NULL), '[^,]+', 1, level) is not null
)b
where a.ordernr=b.order_content
)c
)
where a.ordernr in(
select distinct regexp_substr(replace(orders_from,'[ORDERS]',NULL),'[^,]+', 1, level)
from orders where sub_orders=0
and ORDERS_FROM is not null
connect by regexp_substr(replace(orders_from,'[ORDERS]',NULL), '[^,]+', 1, level) is not null
)

Ich hba mal die fiktive Spalte PAYDATE hinzugenommen. Weitere Spalten müssen einfach in die Selects und die Updateliste aufgenommen werden.
 
Zurück
Oben