Klaus Mock: mySQL: komplizierter (?) Select

Beitrag lesen

Hallo,

SELECT po.* FROM projects_overview AS po, customer_data AS cd, faktura_saetze AS fs WHERE (('1041375600' <= unix_timestamp(po.p_end) AND '1072825200' >= unix_timestamp(po.p_end)) OR ('1041375600' <= unix_timestamp(po.p_start) AND '1072825200' >= unix_timestamp(po.p_start)) OR ('1041375600' <= unix_timestamp(po.p_start) AND '1072825200' <= unix_timestamp(po.p_end))) AND cd.cust_id = po.p_cust_id AND fs.faktura_satz_id = cd.faktura_satz_id AND fs.faktura_op_rev LIKE 'Ext. Erlöse'

Ich verstehe nicht, wie man sinnvoll Abfragen schreiben kann, die in so einer Wurst hingeschrieben sind. Bitte beginne erstmals damit die Abfragen besser zu formatieren, um die Leserlichkeit zu erhöhen. [1]

Dann macht es imho auch Sinn, die WHERE-Klausel so zu schreiben, daß zuerst die Join-Bedingungen stehen[2] und dann erst die eigentlichen einschränkenden Kriterien.

Beispiel:
SELECT po.*
  FROM projects_overview AS po,
       customer_data AS cd,
      faktura_saetze AS fs
  WHERE cd.cust_id = po.p_cust_id
    AND fs.faktura_satz_id = cd.faktura_satz_id
    AND fs.faktura_op_rev LIKE 'Ext. Erlöse'
    AND (('1041375600' <= unix_timestamp(po.p_end)   AND '1072825200' >= unix_timestamp(po.p_end))
      OR ('1041375600' <= unix_timestamp(po.p_start) AND '1072825200' >= unix_timestamp(po.p_start))
      OR ('1041375600' <= unix_timestamp(po.p_start) AND '1072825200' <= unix_timestamp(po.p_end)))

Wo ist der Fehler?

Versuche es erstmals ohne den einschränkenden Bedingungen, damit Du siehst, ob die Joins richtig arbeiten.
Dann erst füge die Einschränkungen dazu.
Ich könnte mir beispielsweise vorstellen, daß es Probleme bei dem 'Ext. Erlöse' gibt und zwar wegen des Umlautes oder wegen der Groß-Klein-Schreibung. Abegesehen davon ist LIKE in diesem Falle unnötig, da Du ja nach exakt diesem text suchen willst.

Dann sieht es mir so aus, als ob faktura_op_rev prädestiniert für den Einsatz einer Schlüsseltabelle wäre, mit einer Integer-ID und einem beschreibenden Text.

Außerdem finde ich die zeitliche Einschränkung ungeschickt.
Zum einen diese unhandliche Formulierung über unix_timestamp-Konstanten. Ich denke daß muß leserlicher gehen (beispielsweise mit "unix_timestamp('1.1.2003') <= unix_timestamp(po.p_start)", aber da wird die DBMS-Dokumenattion sicherlich mehr dazu wissen.)

Und dann verstehe ich die Logik dahinter nicht. Es schein ja so zu sein, daß entweder p_start oder p_end im Zeitfenster liegen muß.
Wenn ich jetzt nochmals postuliere, daß p_start vor p_end sein muß, frage ich mich wozu dann die dritte Bedingung gut sein soll. Naja, das  ist, so, wie ich es sehe, maximal noch ein Performance-Problem.

Grüße
  Klaus

[1] Das Problem habe anscheinend viele Anwender, da man beispielsweise in diesem Forum sehr oft solche Moloche sieht.
[2] Sofern man nicht, wenn möglich, JOIN-Klauseln verwendet, die in den meisten Datenbankensystemen, die diese unterstützen, die Performance besser ist.