Twilo: SQL Syntax optimieren

Hallo,

welcher Syntax ist eigentlich besser?

-----------------

SELECT DISTINCT ROUND((  
(groesse._breite / 1000 * groesse._hoehe / 1000* auflage._auflage * gewicht._bedrgewicht/1000 * groesse._bedrkosten) +  
((farbe._vorderfarbe + farbe._rueckfarbe) * produkt._plattenkosten) +  
((((farbe._vorderfarbe + farbe._rueckfarbe) * produkt._ruestzeitproplatte/60) + ((auflage._auflage / CEIL(produkt._bogengroesse / (groesse._breite / 1000 * groesse._hoehe / 1000 * 1.1))) / produkt._maschinengeschwindigkeit) + produkt._einrichtzeit/60) * produkt._maschinenstundensatz) +  
(produkt._bogengroesse * gewicht._bedrgewicht/1000 * groesse._bedrkosten * produkt._einrichtboegen) +  
ceil(groesse._breite / 1000 * groesse._hoehe / 1000 * auflage._auflage * gewicht._bedrgewicht/1000 * versandart._versdandt) *  
faktor._faktor), 2) AS preis  
  
FROM `t1_produkt` AS produkt, `t1_fracht` AS ffracht  
  
INNER JOIN t1_gewinnfaktor AS faktor ON faktor._gewinnfaktor_id = produkt._gewinnfaktor_id  
INNER JOIN t1_produkt_has_farbe ON t1_produkt_has_farbe._produkt_id = produkt._produkt_id  
INNER JOIN t1_farbe AS farbe ON farbe._farb_id = t1_produkt_has_farbe._farb_id  
INNER JOIN t1_produkt_has_versandart ON t1_produkt_has_versandart._produkt_id = produkt._produkt_id  
INNER JOIN t1_versandart AS versandart ON versandart._versandart_id = t1_produkt_has_versandart._versandart_id  
INNER JOIN t1_produkt_has_auflage ON t1_produkt_has_auflage._produkt_id = produkt._produkt_id  
INNER JOIN t1_auflage AS auflage ON auflage._auflage_id = t1_produkt_has_auflage._auflage_id  
INNER JOIN t1_produkt_has_gewicht ON t1_produkt_has_gewicht._produkt_id = produkt._produkt_id  
INNER JOIN t1_gewicht AS gewicht ON gewicht._gewicht_id = t1_produkt_has_gewicht._gewicht_id  
INNER JOIN t1_produkt_has_groesse ON t1_produkt_has_groesse._produkt_id = produkt._produkt_id  
INNER JOIN t1_groesse AS groesse ON groesse._groesse_id = t1_produkt_has_groesse._groesse_id  
  
INNER JOIN t1_fracht_has_produkt AS fprodukt ON fprodukt._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_farbe AS ffarbe ON ffarbe._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_gewicht AS fgewicht ON fgewicht._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_groesse AS fgroesse ON fgroesse._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_auflage AS fauflage ON fauflage._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_versandart AS fversandart ON fversandart._fracht_id = ffracht._fracht_id  
  
WHERE produkt._produkt_id = 3 AND gewicht._gewicht_id = 1 AND groesse._groesse_id = 6 AND farbe._farb_id = 3 AND auflage._auflage_id = 1 AND versandart._versandart_id = 1

-----------------

oder dieser
-----------------

SELECT DISTINCT ROUND((  
(groesse._breite / 1000 * groesse._hoehe / 1000* auflage._auflage * gewicht._bedrgewicht/1000 * groesse._bedrkosten) +  
((farbe._vorderfarbe + farbe._rueckfarbe) * produkt._plattenkosten) +  
((((farbe._vorderfarbe + farbe._rueckfarbe) * produkt._ruestzeitproplatte/60) + ((auflage._auflage / CEIL(produkt._bogengroesse / (groesse._breite / 1000 * groesse._hoehe / 1000 * 1.1))) / produkt._maschinengeschwindigkeit) + produkt._einrichtzeit/60) * produkt._maschinenstundensatz) +  
(produkt._bogengroesse * gewicht._bedrgewicht/1000 * groesse._bedrkosten * produkt._einrichtboegen) +  
ceil(groesse._breite / 1000 * groesse._hoehe / 1000 * auflage._auflage * gewicht._bedrgewicht/1000 * versandart._versdandt) *  
faktor._faktor), 2) AS preis  
  
FROM `t1_produkt` AS produkt  
  
INNER JOIN t1_gewinnfaktor AS faktor ON faktor._gewinnfaktor_id = produkt._gewinnfaktor_id  
INNER JOIN t1_produkt_has_farbe ON t1_produkt_has_farbe._produkt_id = produkt._produkt_id  
INNER JOIN t1_farbe AS farbe ON farbe._farb_id = t1_produkt_has_farbe._farb_id  
INNER JOIN t1_produkt_has_versandart ON t1_produkt_has_versandart._produkt_id = produkt._produkt_id  
INNER JOIN t1_versandart AS versandart ON versandart._versandart_id = t1_produkt_has_versandart._versandart_id  
INNER JOIN t1_produkt_has_auflage ON t1_produkt_has_auflage._produkt_id = produkt._produkt_id  
INNER JOIN t1_auflage AS auflage ON auflage._auflage_id = t1_produkt_has_auflage._auflage_id  
INNER JOIN t1_produkt_has_gewicht ON t1_produkt_has_gewicht._produkt_id = produkt._produkt_id  
INNER JOIN t1_gewicht AS gewicht ON gewicht._gewicht_id = t1_produkt_has_gewicht._gewicht_id  
INNER JOIN t1_produkt_has_groesse ON t1_produkt_has_groesse._produkt_id = produkt._produkt_id  
INNER JOIN t1_groesse AS groesse ON groesse._groesse_id = t1_produkt_has_groesse._groesse_id  
  
INNER JOIN t1_fracht AS ffracht ON ffracht._fracht_id = fprodukt._fracht_id  
INNER JOIN t1_fracht_has_produkt AS fprodukt ON fprodukt._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_farbe AS ffarbe ON ffarbe._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_gewicht AS fgewicht ON fgewicht._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_groesse AS fgroesse ON fgroesse._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_auflage AS fauflage ON fauflage._fracht_id = ffracht._fracht_id  
INNER JOIN t1_fracht_has_versandart AS fversandart ON fversandart._fracht_id = ffracht._fracht_id  
  
WHERE produkt._produkt_id = 3 AND gewicht._gewicht_id = 1 AND groesse._groesse_id = 6 AND farbe._farb_id = 3 AND auflage._auflage_id = 1 AND versandart._versandart_id = 1

-----------------

kann man unter MySQL 4.1 die Formel in Zwischenschritte untergliedern?
groesse._breite / 1000 * groesse._hoehe / 1000* auflage._auflage * gewicht._bedrgewicht/1000 * groesse._bedrkosten
kommt z.B. 3mal vor

beide Abfragen brauchen laut phpMyAdmin ca. 0.0035 Sekunden

Gibt es eine Möglichkeit, wie man die Abfrage allgemein optimieren kann?

Die SQL Befehle ohne DISTINCT geben 41.280 Datensätze zurück...
ich fage mich wieso... eigentlich dürfte nur einer rauskommen
ist da irgendwo ein Join Problem, dass er soviele (immer das gleiche Ergebnis) Datensätze anzeigt?

mfg
Twilo

  1. Bitte Twilo,

    welcher Syntax ist eigentlich besser?

    das heißt: "Welche Syntax ist eigentlich besser?"!

    Zwei ellenlange Statements, einziger Unterschied der CROSS JOIN im ersten Fall, der INNER JOIN im zweiten Fall, warum machst Du es Deinen potentiellen Helfern so schwer? Wenn ein INNER JOIN existiert, dann schreib' das auch hin. Also ist meiner Meinung nach die zweite Variante sauberer (und portabler). Der Umgang von MySQL mit CROSS JOINs variiert zwischen MySQL-Versionen und steht zum Teil im Widerspruch zu den SQL-Standards.

    kann man unter MySQL 4.1 die Formel in Zwischenschritte untergliedern?
    groesse._breite / 1000 * groesse._hoehe / 1000* auflage._auflage * gewicht._bedrgewicht/1000 * groesse._bedrkosten
    kommt z.B. 3mal vor

    Was hast Du versucht?

    beide Abfragen brauchen laut phpMyAdmin ca. 0.0035 Sekunden
    Gibt es eine Möglichkeit, wie man die Abfrage allgemein optimieren kann?

    Frag' die Datenbank, nutze EXPLAIN.

    Die SQL Befehle ohne DISTINCT geben 41.280 Datensätze zurück...
    ich fage mich wieso... eigentlich dürfte nur einer rauskommen

    warum? Woher sollen wir das wissen? Du hast uns keinen einzigen Deiner Datensätze verraten. Offensichtlich gibt es eben 41.280 verschiedene Möglichkeiten, diese Datensätze in Deinem komplexen JOIN miteinander zu kombinieren, wobei stets der gleiche Preis rauskommt. Wo ist das Problem? Hast Du Rouvens und meinen Artikel zu JOINs gelesen?

    ist da irgendwo ein Join Problem, dass er soviele (immer das gleiche Ergebnis) Datensätze anzeigt?

    Möglicherweise hast Du ein Verständnisproblem, was JOINs betrifft - und machst falsche Annahmen. Zwar hat auch MySQL 4.1 Verständnisproblem, was JOINs betrifft und liefert in bestimmten Fällen systematisch falsche Ergebnisse - aber nicht bei ausschließlicher Verwendung von INNER JOINs wie in Deinem Fall.

    Freundliche Grüße

    Vinzenz

    1. Hallo,

      welcher Syntax ist eigentlich besser?

      das heißt: "Welche Syntax ist eigentlich besser?"!

      ok ;-)

      Zwei ellenlange Statements, einziger Unterschied der CROSS JOIN im ersten Fall, der INNER JOIN im zweiten Fall, warum machst Du es Deinen potentiellen Helfern so schwer? Wenn ein INNER JOIN existiert, dann schreib' das auch hin. Also ist meiner Meinung nach die zweite Variante sauberer (und portabler). Der Umgang von MySQL mit CROSS JOINs variiert zwischen MySQL-Versionen und steht zum Teil im Widerspruch zu den SQL-Standards.

      kann man unter MySQL 4.1 die Formel in Zwischenschritte untergliedern?
      groesse._breite / 1000 * groesse._hoehe / 1000* auflage._auflage * gewicht._bedrgewicht/1000 * groesse._bedrkosten
      kommt z.B. 3mal vor

      Was hast Du versucht?

      bis jetzt noch nichts, da ich unter mysql.com kein passenden Abschnitt gefunden habe

      beide Abfragen brauchen laut phpMyAdmin ca. 0.0035 Sekunden
      Gibt es eine Möglichkeit, wie man die Abfrage allgemein optimieren kann?

      Frag' die Datenbank, nutze EXPLAIN.

      die Ausgabe von EXPLAIN sieht bei beiden wie folgt aus
      id select_type  table                      type    possible_keys                                 key                    key_len  ref                                      rows  Extra
      1  SIMPLE       produkt                    const   PRIMARY,_gewinnfaktor_FKindex                 PRIMARY                4        const                                    1     Using temporary
      1  SIMPLE       faktor                     const   PRIMARY                                       PRIMARY                4        const                                    1
      1  SIMPLE       t1_produkt_has_farbe       const   PRIMARY,_farb_FKindex,_produkt_FKindex        PRIMARY                8        const,const                              1     Using index
      1  SIMPLE       farbe                      const   PRIMARY                                       PRIMARY                4        const                                    1
      1  SIMPLE       t1_produkt_has_versandart  const   PRIMARY,_versandart_FKindex,_produkt_FKindex  PRIMARY                8        const,const                              1     Using index
      1  SIMPLE       versandart                 const   PRIMARY                                       PRIMARY                4        const                                    1
      1  SIMPLE       t1_produkt_has_auflage     const   PRIMARY,_produkt_FKindex,_auflage_FKindex     PRIMARY                8        const,const                              1     Using index
      1  SIMPLE       auflage                    const   PRIMARY                                       PRIMARY                4        const                                    1
      1  SIMPLE       t1_produkt_has_gewicht     const   PRIMARY,_gewicht_FKindex,_produkt_FKindex     PRIMARY                8        const,const                              1     Using index
      1  SIMPLE       gewicht                    const   PRIMARY                                       PRIMARY                4        const                                    1
      1  SIMPLE       t1_produkt_has_groesse     const   PRIMARY,_produkt_FKindex,_groesse_FKindex     PRIMARY                8        const,const                              1     Using index
      1  SIMPLE       groesse                    const   PRIMARY                                       PRIMARY                4        const                                    1
      1  SIMPLE       ffracht                    index   PRIMARY                                       _aktiv_status_FKindex  1        NULL                                     3     Using index; Distinct
      1  SIMPLE       fprodukt                   ref     _fracht_FKindex                               _fracht_FKindex        4        usrdb_schwetbq_druck.ffracht._fracht_id  1     Using index; Distinct
      1  SIMPLE       fversandart                ref     PRIMARY,_fracht_FKindex                       _fracht_FKindex        4        usrdb_schwetbq_druck.ffracht._fracht_id  1     Using index; Distinct
      1  SIMPLE       fgewicht                   ref     PRIMARY,_fracht_FKindex                       _fracht_FKindex        4        usrdb_schwetbq_druck.ffracht._fracht_id  3     Using index; Distinct
      1  SIMPLE       fgroesse                   ref     PRIMARY,_fracht_FKindex                       _fracht_FKindex        4        usrdb_schwetbq_druck.ffracht._fracht_id  3     Using index; Distinct
      1  SIMPLE       fauflage                   ref     PRIMARY,_fracht_FKindex                       _fracht_FKindex        4        usrdb_schwetbq_druck.ffracht._fracht_id  3     Using index; Distinct
      1  SIMPLE       ffarbe                     ref     PRIMARY,_fracht_FKindex                       _fracht_FKindex        4        usrdb_schwetbq_druck.ffracht._fracht_id  3     Using index; Distinct

      Die SQL Befehle ohne DISTINCT geben 41.280 Datensätze zurück...
      ich fage mich wieso... eigentlich dürfte nur einer rauskommen

      warum? Woher sollen wir das wissen? Du hast uns keinen einzigen Deiner Datensätze verraten. Offensichtlich gibt es eben 41.280 verschiedene Möglichkeiten, diese Datensätze in Deinem komplexen JOIN miteinander zu kombinieren, wobei stets der gleiche Preis rauskommt. Wo ist das Problem? Hast Du Rouvens und meinen Artikel zu JOINs gelesen?

      Möglicherweise hast Du ein Verständnisproblem, was JOINs betrifft - und machst falsche Annahmen. Zwar hat auch MySQL 4.1 Verständnisproblem, was JOINs betrifft und liefert in bestimmten Fällen systematisch falsche Ergebnisse - aber nicht bei ausschließlicher Verwendung von INNER JOINs wie in Deinem Fall.

      könntest du bitte den Link posten?

      mfg
      Twilo

  2. yo,

    welcher Syntax ist eigentlich besser?

    wie Vinzenz schon ansprach, ist der unterschied der beiden tabellen, dass in der ersten abfrage eine JOIN bedingung fehlt, nämlich von Tabelle "t1_fracht AS ffracht". ich denke mal, du hast sie nur vergessen hinzuschreiben oder fehlt sie tatsächlich ?

    beide Abfragen brauchen laut phpMyAdmin ca. 0.0035 Sekunden

    ob man nun expliziet die INNER JOIN schreibweise benutzt oder alle JOIN bedingungen in die WHERE klausel mit rein nimmt, ist nur eine frage der übersicht. für die ausführungsgeschwindigkeit spielt sie keine rolle. deine zeitmessung bestätigt diese annahme.

    Gibt es eine Möglichkeit, wie man die Abfrage allgemein optimieren kann?

    das hängt in erster linie von deinem datendesign und die art der daten ab. ohne es genau zu wissen, sollte man dein daten-design sollte zumindestens einer weiteren prüfung unterziehen. und auch die tabellennamen scheinen mir nicht ganz sinnvoll zu sein.

    Die SQL Befehle ohne DISTINCT geben 41.280 Datensätze zurück...
    ich fage mich wieso... eigentlich dürfte nur einer rauskommen
    ist da irgendwo ein Join Problem, dass er soviele (immer das gleiche Ergebnis) Datensätze anzeigt?

    dass die datensätze gleich sind, das hängt mit der ausgabe deiner spalten zusammen. würdest du mehr spalten von verschienden tabellen der abfrage ausgeben, würde dir auffallen, dass sich nun nicht mehr alle datensätze gleichen. das liegt daran, dass ein produkt ganz offensichtlich verschiedene eigenschaften besitzt, die in mehrere tabellen aufgeteilt sind. jede dieser eigenschaften wird nun als ein datensatz dargestellt.

    Ilja

    1. Hallo,

      Die SQL Befehle ohne DISTINCT geben 41.280 Datensätze zurück...
      ich fage mich wieso... eigentlich dürfte nur einer rauskommen
      ist da irgendwo ein Join Problem, dass er soviele (immer das gleiche Ergebnis) Datensätze anzeigt?

      dass die datensätze gleich sind, das hängt mit der ausgabe deiner spalten zusammen. würdest du mehr spalten von verschienden tabellen der abfrage ausgeben, würde dir auffallen, dass sich nun nicht mehr alle datensätze gleichen. das liegt daran, dass ein produkt ganz offensichtlich verschiedene eigenschaften besitzt, die in mehrere tabellen aufgeteilt sind. jede dieser eigenschaften wird nun als ein datensatz dargestellt.

      danke für den Tipp, ich werde mal mehrere Spalten abfragen

      mfg
      Twilo