Rolf b: langsame MySQL Abfrage

Beitrag lesen

Hallo tobi85,

doch, ich denke mein SQL passt schon. Und weil die anr in der Artikel_Attribut Tabelle drinsteht, brauchst Du in keinem Fall einen Join zur Artikeltabelle. Zur "Wo ist das noch" Suche reicht ja die ANR. Die Artikeltabelle brauchst Du erst im zweiten Schritt, wenn du die beliebtesten "Auch-Käufe" gefunden hast.

Man kann es sicher noch anders formulieren, mit anderer Anordnung von IN oder einem EXIST, aber ein ordentlicher SQL Optimizer sollte immer was sinnvolles draus machen. Beispielsweise ginge auch das hier, das habe ich gerade im SQL Server gebastelt.

SELECT COUNT(t2.anr) as Anzahl, anr
FROM Artikel_attribut t2 
     JOIN Auftrag_artikel a2 ON a2.atrnr = t2.ATRNR
WHERE t2.anr != '1'
AND a2.auftragnummer IN (SELECT a1.auftragnummer
                         FROM auftrag_artikel a1
                              JOIN artikel_attribut t1 ON a1.atrnr = t1.atrnr
                         WHERE a1.date > '2016-04-01' AND t1.anr = '1')
GROUP BY t2.anr
ORDER BY COUNT(t2.anr) desc

Der Select im IN ermittelt alle Auftragsnummern seit 01.04.16, wo Hosen dabei waren (ANR=1), der äußere Select sucht zu diesen Aufträgen alle Artikel, die keine Hosen sind. Und die werden dann gruppiert.

ABER ACHTUNG. Wenn dein Shop erfolgreich ist, wirst Du aber auch bei dem besten SQL irgendwann ein Performance-Problem bekommen. Die korrekte Lösung heißt: Prepared Data. Das ist eine Tabelle, die Du nicht live pflegst, sondern in einem Batchjob, z.B. morgens um 3. Die einfachste Prepared Data Lösung würde eine Tabelle sein, die Auftragsnummer, Auftragsdatum und ANR kombiniert, damit Du den Join Auftrag_Artikel mit Artikel_Attribut nicht live machen musst. Wenn auch das zu langsam ist, brauchst Du eine Tabelle mit Spalten "ANR_gekauft", "ANR_auchgekauft", "Anzahl_Aufträge", "Kaufdatum", wo Du dann einfach mit der Hose einsteigst und dann die auch gekauften ANR mit der Anzahl der Aufträge, in denen das der Fall ist, herausbekommst ohne irgendwas zu Joinen. Das läuft dann irgendwann nachts eine Stunde lang und bei der Gelegenheit löschst Du dann auch gleich alles aus der Referenztabelle heraus, was zu alt ist (in deinem Beispiel: Älter als 04.01.2016), damit keine unnötigen Daten durchsucht werden. Für diesen Batch-SQL kannst Du dann aber kein WHERE...IN verwenden, der muss meinem ersten Versuch mit dem 4-fach Join ähneln (Wie genau? Das ist eine Übung für den Leser :-> ). Damit bist Du dann tagsüber flott unterwegs. Zwar nur mit den Daten bis gestern, aber das ist bei dieser Aufgabe wohl weniger relevant.

Gruß Rolf