heinetz: MySQL 5.0.67 | Hilfe bei SQL-Aufgabenstellung

Hallo Forum,

ich versuche mal die Aufgabe auf ein Beispiel zu reduzieren:

Es gibt ein Tabelle 'products', in der, was sonst, Produkte
als Datensätze gespiechert werden. Diese Produkte kennzeichnet
das Feld 'id' als eindeutiger Schlüssel. Da die Produkte in
einer bestimmten Reihenfolge angezeigt werden sollen, gibt es
ausserdem ein Feld 'position'.

Jetzt wird es etwas komplizierter:
Produkte sind entweder (Haupt-)Produkte einer 'Wahrengruppe',
oder (Unter-)Produkte eines anderen Produkts. Es gibt also noch
zwei Felder 'group_key' und 'group_value'.

Die Tabelle sieht folgendermassen aus:

+----------+------------+-------------+----------+
|       id |  group_key | group_value | position |
+==========+============+=============+==========+
|       52 |   products |          41 |        2 |
+----------+------------+-------------+----------+
|       47 | waregroups |           2 |        1 |
+----------+------------+-------------+----------+
|       44 | waregroups |           1 |        1 |
+----------+------------+-------------+----------+
|       43 |   products |          41 |        1 |
+----------+------------+-------------+----------+
|       41 | waregroups |           1 |        2 |
+----------+------------+-------------+----------+
|       61 |   products |          47 |        1 |
+----------+------------+-------------+----------+

Es gibt also die 3 (Haupt-)produkte 47, 44, 41,
zu dem (Haupt-)produkt 47 das (Unter-)produkt 61 und
zu dem (Haupt-)produkt 41 die (Unter-)produkte 43 und 52

Die 'position' beschreibt die Position innerhalb der
Gruppe. Beispielsweis ist die Position des (Haupt-)produkts
44 dessen Position innerhalb der Wahrengruppe 1, die
Position des (Unter-)produkts 43 dessen Position innerhalb
des übergeordneten (Haupt-)produkts 41.

Jetzt zu meiner Aufgabe:
------------------------
Die Produkte 44 und 41 haben hierrarchisch die gleiche
Qualität. Sie sind beide Produkte der Warengruppe 1. Die
Reihenfolge innerhalb der Gruppe, also das Feld 'position',
legt fest, dass 44 an erster und 41 an zweiter Stelle
angezeigt wird und die will ich ändern!

41 soll an die erste Stelle und 44 an die zweite rücken.

Das geht ja erstmal einfach:

die Position 1 erstmal freimachen:

  
UPDATE `products` SET `position` = '2' WHERE `products`.`id` =44;  

die Position neu belegen:

  
UPDATE `products` SET `position` = '1' WHERE `products`.`id` =41;  

Jetzt weiss ich aber nicht, ob und wenn dann welches Produkt
die erste Stelle besetzt. Ich kenne nur den Datensatz, des
Produkts 41. Die Aufgabe lautet also eigentlich:

41 soll an die erste Stelle und das Produkt dieser Gruppe,
was im Moment diese Stelle besetzt, soll an die Stelle von
41 rücken.

Ich müsste also erst die id des Produkts herausfinden, dass die
position 1 besetzt und mir diese merken. Dann müsste ich die
jetzige Position des Produkts 41 herausfinden und mir die merken.
Dann könnte ich mit den beiden Werten, die ich in Variablen
zwischenspeichern müsste die zwei SQL-Statements zusammenbauen.

Ich frage mich, ob das mit einem ausgefeilten SQL-Statement,
vielleicht mit Subselect, geht. Ich habe folgendes probiert:

die Position 1 freimachen:

  
UPDATE `products`  
SET `position` =  
(SELECT `position` FROM `products` WHERE `products`.`id` = 41)  
WHERE `products`.`id` =44;  

... das funktionierte erstmal nicht ;(

Kann mir dabei jemand weiter helfen ?

danke und

beste gruesse,
heinetz

  1. yo,

    Kann mir dabei jemand weiter helfen ?

    weiß nicht genau, ob mysql das inzwischen kann....

    UPDATE products p
    SET position = CASE
                       WHEN p.id <> 41 THEN (SELECT p2.Position
                                             FROM products p2
                                             WHERE p2.id = 41
                                            )
                       ELSE 1
                   END
    WHERE p.id IN (SELECT 41
                   FROM dual -- das ist Oracle, keine ahnung für mysql
                   UNION ALL
                   SELECT p2.id
                   FROM products p2
                   WHERE p2.group_key = p.group_key
                   AND p2.group_value = p.group_value
                   AND p2.position = 1
                  )
    ;

    Ilja

    1. Hi!

      weiß nicht genau, ob mysql das inzwischen kann....

      Nein. Das Ändern von Tabellen beim gleichzeitigen Abfragen derselben in einer Subquery ist nicht möglich. Man könnte sich aber zu Fuß eine temporäre Tabelle als Zwischenspeicher anlegen.

      CASE
        WHEN [...] THEN [...]
        ELSE 1
      END

      So ein einteiliges CASE-WHEN-ELSE kann man auch mit der IF()-Funktion abkürzen.

      [...] SELECT 41 FROM dual -- das ist Oracle, keine ahnung für mysql [...]

      MySQL kann auch ohne FROM selektieren. Das Hilfskonstrukt "dual" benötigt man nicht.

      Lo!

      1. yo,

        Nein. Das Ändern von Tabellen beim gleichzeitigen Abfragen derselben in einer Subquery ist nicht möglich.

        hmm, da muss mysql dann noch mal nachlegen.

        So ein einteiliges CASE-WHEN-ELSE kann man auch mit der IF()-Funktion abkürzen.

        gibt sicherlich viele wege für eine fallunterschiedung, ich mag die case variante, da sie so oftmals in allen rdbms unterstützt wird.

        MySQL kann auch ohne FROM selektieren. Das Hilfskonstrukt "dual" benötigt man nicht.

        und da sollte oracle endlichmal nachlegen, den unsiin mit dual lassen. aber 11.2g ist ja gerade erst rausgekommen....

        Ilja

  2. Hallo Jungs,

    dahinter dass ich kein Subselect auf die Tabelle ausführen
    kann, die ich updaten will, bin ich dann auch gekommen.
    Danke für eure Beiträge. Mein Problem sitzt tiefer ;(

    beste gruesse,
    heinetz