Rolf B: MySQL Abfrage

Beitrag lesen

Hallo mixmastertobsi,

da Du die Artikel-Tabelle nach verschiedenen Kriterien durchsuchst, wird ein doppelter Zugriff unumgänglich sein. Aber ich muss zugeben, dass ich dein SQL Statement und deinen fachlichen Wunsch nicht recht verstehe.

Du verwendet diese folgenden Tabellen und Spalten. T ist dein Typ für die aid Spalte, den hast Du nicht angegeben, aber das ist ja auch wurscht. Ich schreibe einfach T.

Tabelle artikel: 
Spalte aid - nullable, T
Spalte kategorie - String

Tabelle artikel_info
Spalte aid - T
Spalte value - T

Diese beiden Tabellen verknüpfst Du per LEFT JOIN, d.h. du nimmst alle Zeilen aus der Artikel-Tabelle und erweiterst sie bei Zutreffen der Join-Bedingung um die Spalten aus der Artikel_Info Tabelle.

Die Join-Bedingung trifft zu, wenn Artikel und Artikel_Info die gleiche AID haben, UND wenn die Spalte value die AID eines Artikels mit Kategorie 10% hat. Dieser innere SELECT würde definitiv von einem Index auf artikel.kategorie profitieren. Ebenso der WHERE des äußeren SELECT. Ohne Index auf artikel.kategorie führen diese SELECTs zu Table Scans auf die 10000 Zeilen der Artikel-Tabelle, mit Index ist es ein Index-Scan.

Das Ganze filterst Du dann und suchst nur die Artikel, deren Kategorie mit 10 beginnt und wo die AID null ist. Das finde ich schon mal merkwürdig - AID klingt nach "Artikel-ID" und die kann null sein? Sind das vorläufige Artikel, die noch keine ID haben?

Ein "NOT" oder "<>" sehe ich nirgends, insofern ist mir nicht ganz klar, wie das die Anforderung „dass manche Artikel nicht angezeigt werden, wenn andere Artikel...angezeigt werden“ erfüllen kann.

Die Frage ist auch, ob eine IN Klausel hier die richtige Lösung ist. IN bestimmt alle AID aus Artikel zur Kategorie 10%, ist also ein Mengen-Select. Aber eigentlich hast Du doch in artikel_info.value eine einzelne aid, gelle, und willst wissen, ob diese aid die Kategorie '10%' hat. Da bietet sich eher eine EXISTS-Abfrage an, die fix ist, wenn Du einen Index auf artikel.aid liegen hast.

SELECT *
FROM artikel a1
     LEFT JOIN artikel_info inf 
          ON  a1.aid = inf.aid
          AND EXISTS (SELECT * FROM artikel a2 WHERE a2.aid=inf.value AND a2.kategorie like '10%')
WHERE ...

Trotzdem muss er aber zumindest für alle Sätze den Subselect machen, die einen artikel_info Eintrag haben. Ob er so schlau ist, den Subselect wegzulassen wenn eine aid keinen Eintrag in artikel_info hat, weiß ich nicht, würde es aber erwarten.

Noch ein Gedanke: je nachdem, wie oft Du diese Abfrage am Tag machst und wie oft sich die Kategorie zu einer AID ändert, kann es sich rentieren, in artikel_info eine Zusatzspalte einzuführen, die die Kategorie zur AID redundant gespeichert ist. Das musst Du natürlich synchron halten - entweder in deinem Programm bei jedem Update auf artikel.kategorie, oder in einem Batchjob. Wie gesagt: KANN sich rentieren. Redundanzen sind zwar Schmiere für die Datenbank, aber keiner macht sich gern die Finger damit fettig.

Rolf

--
sumpsi - posui - clusi