mixmastertobsi: MySQL Abfrage

Hallo,

ich habe mal wieder eine Abfrage, bei welcher ich nicht weiter komme und auch nirgends eine Lösung hierzu finden

Tabelle 1

id | feld
------------
1  | preis1
2  | preis1
3  | preis2

Tabelle 2

id | preis1 | preis2
--------------------
1  | 99     | 199
2  | 120    | 220
3  | 200    | 220

Es soll nun in Tabelle 1 geprüft werden, welche Spalte in Tabelle 2 ausgegeben werden soll.

SELECT ?!? FROM tabelle2 JOIN tabelle1 ON tabelle1.id=tabelle2.id

  1. Hi,

    Es soll nun in Tabelle 1 geprüft werden, welche Spalte in Tabelle 2 ausgegeben werden soll.

    Du suchst nach der IF-Funktion, für MySQL etwa beschrieben hier.

    Bis die Tage,
    Matti

    1. Das ist richtig. Mit IF funbktioniert es auch, aber das ist nicht ganz so toll gelöst - finde ich. Wenn es zum Beispiel nur zwei Preisspalten gibt, ist das OK - aber wenn es mehrere sind, muss ich viele IF Abfragen ineinander verschachteln. Gibt es keine andere Möglichkeit

      SELECT IF(tabelle1="preis1",tabelle2.preis1,tabelle2.preis2) FROM tabelle2 JOIN tabelle1 ON tabelle1.id=tabelle2.id

      Tabelle 1
      id | feld
      ------------
      1  | preis1
      2  | preis1
      3  | preis2
      4  | preis3
      5  | preis4
      6  | preis1
      7  | preis2

      Tabelle 2

      id | preis1 | preis2 | preis3 | preis4
      --------------------------------------
      1  | 99     | 199    | 399    | 199
      2  | 120    | 220    | 99     | 2199
      3  | 200    | 220    | 99     | 1199

      1. Hallo,

        wenn die Preisspalten variabel sein sollen, würde ich Tabelle 2 so aufbauen:

        id | pid | name    | preis
        ----------------------------
        1  | 1   | preis1  | 399
        2  | 1   | preis2  | 99
        3  | 2   | preis1  | 99
        ...

        Die Spalte "pid" bezieht sich auf "id" von Tabelle 1.

        SELECT preis FROM Tabelle2 WHERE pid=... AND name='...'

        Grüße Basti

      2. Hallo,

        Das ist richtig. Mit IF funbktioniert es auch, aber das ist nicht ganz so toll gelöst - finde ich. Wenn es zum Beispiel nur zwei Preisspalten gibt, ist das OK - aber wenn es mehrere sind, muss ich viele IF Abfragen ineinander verschachteln. Gibt es keine andere Möglichkeit

        Tabelle 2

        id | preis1 | preis2 | preis3 | preis4

        1  | 99     | 199    | 399    | 199
        2  | 120    | 220    | 99     | 2199
        3  | 200    | 220    | 99     | 1199

        doch. Ganz klar. Diese kaputte Struktur, auf die Dich Patrick hingewiesen hat, schleunigst bereinigen.

        Tabelle2

        id | preisklasse | preis
        ------------------------
         1 |           1 |    99
         1 |           2 |   199
         1 |           3 |   399
         1 |           4 |   199
         2 |           1 |   120

        ...

        und ein unique-Index über die Spaltenkombination id, preistyp sorgt dafür, dass es keinen doppelten Preis für den gleichen Artikel und die gleiche Preisklasse gibt. Nun kannst Du soviele Preistypen haben, wie Du willst und selbstverständlich auch für unterschiedliche Artikel verschieden viele Preisklassen.

        Freundliche Grüße

        Vinzenz

      3. Hi!

        Mit IF funbktioniert es auch, aber das ist nicht ganz so toll gelöst - finde ich. Wenn es zum Beispiel nur zwei Preisspalten gibt, ist das OK - aber wenn es mehrere sind, muss ich viele IF Abfragen ineinander verschachteln. Gibt es keine andere Möglichkeit

        Du hast zum einen Spaltennamen in den Daten. Dafür brauchst du immer einen Umsetzer, denn es gibt keine Funktion, die den Inhalt eines Feldes in einen Spaltennamen umwandelt. Und wenn du das Problem hast, dass es mehr als 1 Element pro Datensatz gibt, dann macht man dafür nicht n Spalten sondern nimmt eine 1:n-Verknüpfung. Dann ergibt sich auch das derzeit mit IF() gelöste Problem nicht, weil man dann einfach joinen oder "subqueryen" kann.

        Lo!

      4. Hi,

        Gibt es keine andere Möglichkeit

        Wie schon gesagt wurde, Dein Tabellenmodel ist falsch. Zumindest wenn man normale Anwendungsfälle vorrausetzt. Sollte es also keinen wirklich trifftigen Grund geben die Tabellen so anzulegen wie Du es getan hast, empfehle ich die Modulation.

        Tabelle 1 kann so bleiben, Tabelle 2 ist dann die Verknüpfungstabelle und sollte so aufgebaut sein:

        id | tab1_preis | preis (tab 3)
        -----------------------
        1  | 1          |  1
        2  | 1          |  2
        3  | 2          |  5
        4  | 3          |  2
        5  | 4          |  1
        6  | 1          |  3

        dazu kommt Tab 3 die nur die Preise enthält. (Siehe erste Normalform keine Redundanzen wie bei Dir in Tab 2)

        id | preis
        ----------
         1 | 99
         2 | 199
         3 | 120
         4 | 220
         5 | 399

        Viele Grüße,
        Rob

        1. Servus,

          dazu kommt Tab 3 die nur die Preise enthält. [...]

          Das geht dann doch einen Schritt zu weit und hat nichts mehr mit Normalisierung zu tun.
          Auch wenn zwei Preise zufälig denselben Wert haben sind sie dennoch verschiedene Entities. Oder von der anderen Seite betrachtet: Wenn sich der Preis von Produkt X ändert, soll sich dann auch der Preis aller anderen Produkte mit demselben Preis ändern? Unwahrscheinlich.

          Es wird wohl in die Richtung gehen, die Vinzenz angedeutet hat. Ob man das nun über Preisklassen abbildet, mittels eines "aktiv"-Flags oder anders hängt, wie ich bereits sagte, vom vorliegenden Business Case ab.

          Gruss
          Patrick

          1. Ich vergaß noch zu erwähnen:
            Es kann auch durchaus sinnvoll sein, alle Preise in Tabelle1 zu speichern. Aber wie gesagt müsste man für genaueres wissen, was du erreichen willst.

  2. Servus,

    die Struktur deiner Daten ist gelinde gesagt kaputt. Um dir an der Stelle konkret weiterhelfen zu können fehlen allerdings Informationen zum Business Case.

    Gruss
    Patrick

    1. warum kaputt?!?

      1. Moin!

        warum kaputt?!?

        Weil man nicht zweimal dasselbe in ZWEI Spalten tut, hier den "preis1" und "preis2", wenn man am Ende irgendwo die Entscheidung trifft, nur jeweils einen Preis davon verwenden zu wollen.

        Lösung: Preise nur in EINER Spalte speichern (dann weißt du auch, was du selektieren willst), und wenn die zwei Preise irgendeine Bedeutung haben, z.B. einen bestimmten Typ, dann definiere eine zweite Spalte, die den Preistyp angibt. Und dein Select wird dann nur den Preistyp nehmen, der gefordert ist.

        - Sven Rautenberg

  3. Nach Anraten in diesem Forum, werde ich nun die Datenbank neu aufbauen.
    Jedoch klappt die erste Abfrage schon nicht.

    Früher hatte ich die Datenbank wie folgt
    artikelnr | preis |attribut1 | attribut2
    ----------------------------------------
    1         | 9.99  |GR1       | Rot
    2         | 10.00 |GR3       | Blau

    Nun habe ich diese Datenbank aufgegliedert

    Tabelle 1

    artikelnr | preis
    -----------------
    1         | 9.99
    2         | 10.00

    Tabelle 2

    artikelnr | attribut
    --------------------
    1         | GR1
    1         | Rot
    2         | Blau
    2         | GR3

    Jetzt versuche ich eine Verbindung zwischen Tabelle 1 und 2 herzuestellen und nach den attribut zu  suchen. Jedoch klappt dies nicht wie gewünscht. Folgendes habe ich probiert

    SELECT * FROM tabelle1 JOIN tabelle2 ON tabelle2.artikelnr=tabelle1.artikelnr WHERE tabelle2.attribut='GR1' AND tabelle2.attribut='ROT'

    Wie kann ich die zwei Zeilen von Tabelle 2 mit Tabelle 1 verknüpfen?!?

    1. Servus,

      Früher hatte ich die Datenbank wie folgt [...]

      Eigentlich nicht - zumindest nicht der Auszug, den du uns gezeigt hast. Was ist nun aus den ganzen Preisen geworden?

      Nun habe ich diese Datenbank aufgegliedert [...]

      Das wird so nicht funktionieren. Für jedes Attribut, das du als eigenständiges Entity betrachtest, brauchst du eine eigene Tabelle. Auch referenzierst du dort nicht die Artikelnummer des Produkts, sondern in der Tabelle des Produkts den Primärschlüssel des Attributs, z.B.

      Produkt-Tabelle:

      pk | artikelnr | preis | attribut1_pk | farbe_pk
      --------------------------------------------------
        1 | 12345     |  9.99 | 2            | 1
        2 | 12346     | 10.00 | 3            | 4

      Farb-Tabelle:

      pk | name
      ------------
        1 | Rot
        2 | Grün
        3 | Gelb
        4 | Blau

      Beachte auch, das die Produkt-Tabelle Primärschlüssel braucht. Eine Artikel-Nummer eignet sich nicht als Primärschlüssel, denn diese kann sich ändern. Primärschlüssel werden idR vom DBMS oder der Applikation generiert (in deinem Fall mit Sicherheit ersteres, z.B. mittels AUTO_INCREMENT in MySQL).

      Bevor du das nun aber alles umnudelst solltest du zunächst für jedes Attribut klären, ob es überhaupt Sinn macht, es als eigenes Entity zu betrachten. Bei Produkt-Farben z.B. macht es das normalerweise nicht, bei bspw. Kategorien hingegen fast immer.

      [...] WHERE tabelle2.attribut='GR1' AND tabelle2.attribut='ROT'

      Findest du in deiner Tabelle2 einen Wert für 'attribut', der sowohl GR1 als auch ROT ist?

      Gruss
      Patrick

      1. Das sind ja auch nur Beispiel Tabellen. Die Tabellen sind eigentlich viel komplexer.

        OK - dann mache ich mich mal an werk

        Tabelle1 - Artikel

        artikelnr (Primär) | produkt | beschreibung | Kategorie
        --------------------------------------------------------
        1                  | Artikel1| text         | 10

        Tabelle2 - Ausführung
        atrnr (Primär) | artikelnr | bezeichnung | attribut1 | attribut 2 | attribut3
        -----------------------------------------------------------------------------
        1              | 1         | Rot 100cm   | Rot       | 100 cm     |
        2              | 1         | Blau 100 cm | Blau      | 100 cm     |
        3              | 1         | Gelb 100 cm | Gelb      | 100 cm     |
        4              | 1         | Rot 120cm   | Rot       | 120 cm     |
        .
        .
        .

        Tabelle3 - Attribut-Name
        artikelnr | attribut | name
        ----------------------------
        1         | attribut1| Farbe
        1         | attribut2| Größe

        Ich hoffe es ist einigermaßen verständlich. Nun kann der User in zwei Select-Feldern auswählen

        Feld 1

        • ROT
        • BLAU
        • GELB

        Feld 2
        100 cm
        120 cm

        Von der Datenbank wird die Ausführung ausgegeben, welche der User ausgewählt hat.

        Da mir aber vorhin gesagt wurde, dass die Datenbank "kaputt" ist, wollte ich die attribute in einer weiteren Tabelle ausgeliedern.

        1. moin,

          Ich hoffe es ist einigermaßen verständlich. Nun kann der User in zwei Select-Feldern auswählen

          das größte problem ist oftmals die kommunikation in einem forum, weil im gegensatz zu einem direkten gespräch kein schneller dialog aufkommt, wo man sehr gezielt auch fragen stellen kann. und wichtiger als tabellen oder abfragen sind für uns die fachlichkeiten in worten. nur so kann man eine optimale lösung erarbeiten.

          Da mir aber vorhin gesagt wurde, dass die Datenbank "kaputt" ist, wollte ich die attribute in einer weiteren Tabelle ausgeliedern.

          dies bezüglich gibt es mehrere möglichkeiten. eine wäre es, jedes attribut in eine weitere tabelle auszulagern (kein neuer eigenständiger attributtyp, sondern nur die anwendung der atomaritätsregel). dies kann man machen, wenn die anzahl der attribute vorher bekannt ist und keine weiteren attribute mehr in zukunft dazu kommen oder wenn dann nur ganz selten. man will vermeiden, dass sich das datenbank-design all zu oft ändert und somit anpassungen von nöten sind.

          die andere möglichkeit kommt dann zum tragen, wenn neue attribute sehr dynamisch dazu kommen können. dann erstellt man eine extra tabelle für alle möglichen attributen und typisiert diese aus.

          Ilja

    2. moin,

      SELECT * FROM tabelle1 JOIN tabelle2 ON tabelle2.artikelnr=tabelle1.artikelnr WHERE tabelle2.attribut='GR1' AND tabelle2.attribut='ROT'

      mach mal aus dem AND ein OR und welt wird in einem neuen licht erscheinen. oder noch besser, nimm den IN operator....

      Ilja

  4. Nach Anraten in diesem Forum, werde ich nun die Datenbank neu aufbauen.
    Jedoch klappt die erste Abfrage schon nicht.

    Früher hatte ich die Datenbank wie folgt
    artikelnr | preis |attribut1 | attribut2
    ----------------------------------------
    1         | 9.99  |GR1       | Rot
    2         | 10.00 |GR3       | Blau

    Nun habe ich diese Datenbank aufgegliedert

    Tabelle 1

    artikelnr | preis
    -----------------
    1         | 9.99
    2         | 10.00

    Tabelle 2

    artikelnr | attribut
    --------------------
    1         | GR1
    1         | Rot
    2         | Blau
    2         | GR3

    Jetzt versuche ich eine Verbindung zwischen Tabelle 1 und 2 herzuestellen und nach den attribut zu  suchen. Jedoch klappt dies nicht wie gewünscht. Folgendes habe ich probiert

    SELECT * FROM tabelle1 JOIN tabelle2 ON tabelle2.artikelnr=tabelle1.artikelnr WHERE tabelle2.attribut='GR1' AND tabelle2.attribut='ROT'

    Wie kann ich die zwei Zeilen von Tabelle 2 mit Tabelle 1 verknüpfen?!?