Andre: SQL - Abfrage (logik problem)

Morgen zusammen,

ich habe da ein Problem.
(Gleich vorweg, ich habe keine Einfluß auf die Datenbank-Struktur!)
Folgenden SQL-Befehl habe ich geschrieben und bin eigentlich damit zufrieden:

SELECT
Tabelle4.wert,sum(Tabelle2.menge) AS Menge
FROM
Tabelle1,Tabelle2,Tabelle3,Tabelle4
WHERE
Tabelle1.lieferdatum>="2007-01-01"
AND
Tabelle1.lieferdatum<"2007-02-01"
AND
Tabelle2.auftrag_id=Tabelle1.id
AND
Tabelle3.id=Tabelle2.produkt_id
AND
Tabelle4.produkt_id=Tabelle3.id
AND
Tabelle4.name='länge'
GROUP BY
Tabelle4.wert
ORDER BY
Menge
DESC

Als Ergebniss bekomme ich dann folgendes geliefert:

wert   menge
 ------  -----
 300.0   154.0
 150.0   114.0
 200.0   81.0
 140.0   54.0
 usw...

Ok. Nun möchte ich noch folgendes haben...

Folgender Fall kann eintreten:
Tabelle4.name='länge' kann auch "farbe" enthalten, also: Tabelle4.name='farbe'

Wie muss ich meinen SQL-Befehl erweitern um folgendes als Ergebniss geliefert zu bekommen:

p_wert  farbe  menge
 ------  -----  -----
 300.0   grün   100.0
 300.0   rot     34.0
 300.0   gelb    20.0
 150.0   grün   100.0
 150.0   gelb    14.0
 200.0   grün    81.0
 usw...

Ich komm einfach nicht drauf. Ich glaube die schwierigkeit daran ist das "länge" und "farbe" in einem Feld stehen und ich ja nur nach "farbe" nochmal "Untergruppieren" will.

Vieleicht kann mir ja jemand helfen, ich komm da einfach nicht drauf.
Wäre klasse.

Gruß
Andre

  1. Hi,

    1. zeichne mal bitte die Strukturen der einzelnen Tabellen hier auf, mit Beispielinhalten

    2. Welches Datenbanksystem und welche Version davon

    Deine jetzige Problembeschreibung enthält zuviel Ungenauigkeiten.

    Gruss, Frank

      1. zeichne mal bitte die Strukturen der einzelnen Tabellen hier auf, mit Beispielinhalten

      Tabelle: auftrag
      id
      lieferdatum

      Tabelle: auftragposition
      id
      auftrag_id
      produkt_id
      menge(z.b. 1 oder 3 usw...)

      Tabelle: produkt
      id

      Tabelle: produkteigenschaft
      produkt_id
      wert
      (Wenn Feld: name="länge" dann enthält Feld: wert z.b. 120 oder 240 usw...)
      (Wenn Feld: name="farbe" dann enthält Feld: wert z.b. grün oder rot usw...)
      name (enthält "länge" oder "farbe")

      Das ist die bisherige SQL Abfrage:

      SELECT
      produkteigenschaft.wert,sum(auftragposition.menge) AS Menge
      FROM
      auftrag,auftragposition,produkt,produkteigenschaft
      WHERE
      auftrag.lieferdatum>="2007-01-01"
      AND
      auftrag.lieferdatum<"2007-02-01"
      AND
      auftragposition.auftrag_id=auftrag.id
      AND
      produkt.id=auftragposition.produkt_id
      AND
      produkteigenschaft.produkt_id=produkt.id
      AND
      produkteigenschaft.name='länge'
      GROUP BY
      produkteigenschaft.wert
      ORDER BY
      Menge
      DESC

      Ausgabe:
       wert    menge
       ------  -----
       300.0   154.0
       150.0   114.0
       200.0   81.0
       140.0   54.0
        usw...

      1. Welches Datenbanksystem und welche Version davon

      Informix, aktuellste Version

      Deine jetzige Problembeschreibung enthält zuviel Ungenauigkeiten.

      hoffe die konnte ich jetzt etwas bereinigen

      Gruss, Frank

      Danke Gruß

      1. Wahrscheinlich ist das doch nicht machbar.
        Hab ich mir fast gedacht. Schade.
        SQL kann halt nicht alles ;-)

        Falls es doch machbar ist Ihr aber noch nicht ganz versteht was mein Problem ist dann fragt bitte einfach nochmal.
        Aber ich denke ich hab das im letzten Post doch ganz verständlich aufgezeigt.

        Vielen Dank.

        Gruß

        1. Oder jetzt mal ganz anders gefragt, vieleicht war das erste Beispiel einfach zu komplex/kompliziert!
          Hoffe das ich es so besser und verständlicher erklären kann:

          Tabelle A

          id  wert  name   menge*
          -----------------------
          0    rot   farbe    1
          1    gelb  farbe    2
          0    100   länge    1
          1    100   länge    2
          2    rot   farbe    4
          2    500   länge    4
          3    800   länge    1
          3    lila  farbe    1

          *Menge kommt aus einer anderen Tabelle ist dort eindeutig.
          Hier im Beispiel steht halt bei id 0, farbe rot und bei id 0, länge 100 jeweils 1 obwohl die 1 natürlich für beide zusammen gilt.

          draus soll folgendes Ergebniss angezeigt werden:

          id  länge  farbe  menge
          ------------------------
          0    100    rot     1
          1    100    gelb    2
          2    500    rot     4
          3    800    lila    1

          länge und farbe sind im selben Feld darin sehe ich eben das Problem.
          Gibt es dafür eine lösung das so zu gruppieren und anzeigen zu lassen?

          Danke.

      2. Hi,

        Informix sagt mir primär nix, ausser dass es quasi von IBM stammt.

        Ich hoffe, es unterstützt SQL nach ANSI 92 Standard und damit explizite JOIN syntax. Mit letzterer wird dein SQL auch viel deutlicher lesbar.

          
        SELECT  
                pe1.wert,  
                pe2.wert,  
                sum(auftragposition.menge) AS Menge  
           FROM produkt  
           INNER JOIN produkteigenschaft pe1  
              ON produkt.id = pe1.produkt_id  
              -- und jetzt nur die Produkteingeschaften LÄNGE  
              AND pe1.Name = 'länge'  
           INNER JOIN produkteigenschaft pe2  
              ON produkt.id = pe2.produkt_id  
              -- und jetzt nur die Produkteingeschaften FARBE  
              AND pe2.Name = 'farbe'  
           INNER JOIN auftragposition  
              ON produkt.id = auftragposition.produkt_id  
           INNER JOIN auftrag  
              ON auftragposition.auftrag_id = auftrag.id  
              AND auftrag.lieferdatum BETWEEN "2007-01-01" AND "2007-02-01"  
           GROUP BY pe1.wert,  
                    pe2.wert  
           ORDER BY Menge DESC  
        
        

        Du musst also die Tabelle 'produkteigenschaft' 2x joinen.

        Gruss, Frank

        1. Also ersteinmal ein großes Dankeschön!
          Hab nicht erwartet das du mir gleich den ganzen Code lieferst ;-)
          Aber es funktioniert einwandfrei, genau so wie ich es wollte.

          Mich jetzt nicht undankbar einschätzen, aber ich würde es auch gerne vollständig verstehen ;-)

          [code lang=sql]
          SELECT
                  pe1.wert,
                  pe2.wert,

          hier werden doch Aliasnamen erstellt oder?
          Ich wusste gar nicht das so funktioniert...

          sum(auftragposition.menge) AS Menge
             FROM produktd

          INNER JOIN produkteigenschaft pe1

          Bedeutet das, dass du ein Ergebniss nur für die Variable pe1 holst?

          ON produkt.id = pe1.produkt_id
                -- und jetzt nur die Produkteingeschaften LÄNGE
                AND pe1.Name = 'länge'
             INNER JOIN produkteigenschaft pe2

          Und hier wird das Ergebniss mit farbe in die Variable pe2 geschrieben, oder?

          ON produkt.id = pe2.produkt_id
                -- und jetzt nur die Produkteingeschaften FARBE
                AND pe2.Name = 'farbe'
             INNER JOIN auftragposition
                ON produkt.id = auftragposition.produkt_id

          Wo ist auf Übersichtlicher Betrachtung JOIN besser als ohne?
          Ohne wäre ja dann:

          oben bei SELECT die tabellen auftragposition,produkt schreiben
          und dann in der WHERE Klausel produkt.id = auftragposition.produkt_id. Oder sehe ich da was falsch?

          INNER JOIN auftrag
                ON auftragposition.auftrag_id = auftrag.id
                AND auftrag.lieferdatum BETWEEN "2007-01-01" AND "2007-02-01"

          Ok BETWEEN ist natürlich besser als das vorherige ;-)

          GROUP BY pe1.wert,
                      pe2.wert
             ORDER BY Menge DESC

          Du musst also die Tabelle 'produkteigenschaft' 2x joinen.

          Ja genau, aber ich wusste nicht wie *g*

          Gruss, Frank

          1. Hi nochmal,

            »»»» SELECT
            »»»»         pe1.wert,
            »»»»         pe2.wert,

            hier werden doch Aliasnamen erstellt oder?
            Ich wusste gar nicht das so funktioniert...

            Nein, da werden keine Aliasnamen _erstellt_ sondern hier:

            INNER JOIN produkteigenschaft pe1

            INNER JOIN fügt eine Referenz auf die Tabelle unter dem Alias "pe1" dem Resultset hinzu. Die Spalten der Datensätz von produkteigenschaft, die dem JOIN entsprechen, stehen dann als pe1 zur Verfügung.

            »»»»    INNER JOIN produkteigenschaft pe1
            »»»»       ON produkt.id = pe1.produkt_id
            »»»»       -- und jetzt nur die Produkteingeschaften LÄNGE
            »»»»       AND pe1.Name = 'länge'

            Bedeutet das, dass du ein Ergebniss nur für die Variable pe1 holst?

            Nicht ganz, es bedeutet ich hole alle Datensätze aus 'produkteigenschaft', deren .Name = 'länge' ist als Tabelle in meine Abfrage und nenne sie pe1.

            Warum das Aliasing? Weil du 2x dieselbe Tabelle joinst/brauchst und die DB ohne die unterschiedlichen Aliasnamen nicht wüsste aus welcher Menge eine bestimmte Spalte zu selektieren ist.

            Warum explizite JOIN Syntax besser ist?

            • u.a. weil sie dem Leser direkt das verhältnis zwischen den Ergebnismengen offenlegt und dieser nicht erst geistig die WHERE Klauseln evaluieren muss

            Gruss, Frank

            1. ok, danke schön.
              Bin auch gerade dabei mir das ganze mit den JOINS durchzulesen und zu lernen/verstehen.
              Bis jetzt hab ich JOINS immer ignoriert ;-)

              Dank dir auch jedenfall für dein Hilfe.

              Gruß
              schönen Abend noch...