Daten aus Subquery mit auslesen

timestamp

Mitglied Käsekuchen
Hallo,

ich stehe hier vor einem Problem, dass sich mit der Performance meines Queries gibt.
Die Abfrage braucht ungecachet über 2sek, was deutlich zu lang ist.
Das Problem vermute ich bei einer redundanten Abfrage, der Query sieht vereinfacht so aus:
SQL:
SELECT
a.a, a.b, a.c, m.t
FROM m
LEFT JOIN p
ON p.m_id = m.id
LEFT JOIN a
ON a.id = p.a_id
WHERE
m.id 
IN (
  SELECT m_id 
  FROM p 
  WHERE a_id 
  IN(
    SELECT id 
    FROM a 
   WHERE
   a.a = 'suche' OR a.b = 'suche' or a.c = 'suche'
  )
)

Wie man sieht steht in den Subquerys letztendlich das drin, was ich am Anfang auslesen möchte. Kann ich die Sachen quasi "nach oben" geben?

Tabellen:
Code:
Table m:
id, title

Table a:
id, a, b, c

Table p:
m_id, a_id
 
Wozu überhaubt das Subquery? Du gehst da von a über 'a.id = p.a_id' auf p. Vor dort über 'p.m_id = m.id' auf m. Dann wieder zurück mit 'p.m_id = m.id' auf p und von p mit 'a.id = p.a_id' auf a.

SQL:
SELECT
	a.a, a.b, a.c, m.t
FROM
	m
	LEFT JOIN p
		ON p.m_id = m.id
	LEFT JOIN a
		ON a.id = p.a_id
WHERE
	FIELD('suche', a.a, a.b, a.c) != 0
 
Zuletzt bearbeitet von einem Moderator:
Das liefert mir leider nicht alle Datensätze die ich brauche.

Beispiel:
Code:
Table m:
id, title
1, meinTitel
2, meinTitel2
 
Table a:
1, aaa, bbb, cccc
2, ddd, eee, fff
3, ggg, hhh, iii
 
Table p:
m_id, a_id
1, 1
1, 2
1, 3
2, 1
2, 2
Dein Code liefer mir leider nur a_id1, bzw aaa,bbb,ccc
Ich hätte aber gerne alle a_ids aus der Tabelle p, bzw die dazugehörigen Datensätze aus a.
Wenn ich also nach aaa Suche, hätte ich gerne folgende Ausgabe:
Code:
titel, a.a, a.b, a.c
meinTitel, aaa, bbb, ccc
meinTitel ddd, eee, fff
meinTItel ggg, hhh, iii
meinTItel2, aaa, bbb, ccc
meinTItel2, ddd, eee, fff
 
****?
Für das Resultat brauchst du kein WHERE und keine Suche nach aaa. Das sind nur alle 3 Tabellen verbunden.
 
Doch, das brauche ich:
In Tabelle A stehen die Namen von Autoren,
Tabelle M enthält Bücher, und P bildet paare von Büchern und Autoren.
Zum Beispiel hat das Buch mit der ID 1 laut PaarTabelle die Autoren 1, 2 und 3.

Wenn ich jetzt nach Autor 'aaa' suche, findet er also Buch 1. Zusätzlich möchte ich aber auch noch Autor 2 und 3 mit ausgeben.
 
Dann wars ein schlechtes Beispiel von dir *g*

M brauchen wir also nur für den Buchtitel

Also, mal wie immer ungetestet. Obs schneller ist - testen geht über studieren
SQL:
SELECT
	m.title,
	a.a,
	a.b,
	a.c
FROM
	(
		SELECT
			p_select.a_id
			p_select.m_id
		FROM
			a
			INNER JOIN p AS p_select 		ON p_select.a_id = a.id
			INNER JOIN p AS p_all			ON p_all.m_id = p_select.m_id
		WHERE
			FIELD('suche', a.a, a.b, a.c) != 0
	) AS p1
	INNER JOIN a ON p1.a_id = a.id
	INNER JOIN m ON p1.m_id = m.id
 
Zuletzt bearbeitet von einem Moderator:
Hey Yaslaw,
Danke, dass du zu so "später" Stunde noch Zeit für mich findest.

Dein Query sieht vom Ergebnis nicht schlecht aus (auch vom Timing nicht).
Ich erhalte das Buch jetzt tatsächlich mehrfach, allerdings immer mit Autor "aaa", die anderen Autoren tauchen nicht auf.

Ergebnis:
Code:
titel, a, b, c
MeinTitel, aaa, bbb, ccc
MeinTitel, aaa, bbb, ccc
MeinTitel, aaa, bbb, ccc

So sollte es sein:
Code:
titel, a, b, c
MeinTitel, aaa, bbb, ccc
MeinTitel, ddd, eee, fff
MeinTitel, ggg, hhh, iii

Aus Tabelle m brauche ich tatsächlich noch mehrere Joins auf andere Tabellen, die ich jetzt aus Übersichtsgründen nicht hier aufführe.
 
Möp - logish. Man sollte die IDs von p_all nehmen und nicht uas der p_select
SQL:
SELECT
	m.title,
	a.a,
	a.b,
	a.c
FROM
	(
		SELECT
			-- Hier war der Hund begraben
			p_all.a_id
			p_all.m_id
		FROM
			a
			INNER JOIN p AS p_select 		ON p_select.a_id = a.id
			INNER JOIN p AS p_all			ON p_all.m_id = p_select.m_id
		WHERE
			FIELD('suche', a.a, a.b, a.c) != 0
	) AS p1
	INNER JOIN a ON p1.a_id = a.id
	INNER JOIN m ON p1.m_id = m.id
 
Zuletzt bearbeitet von einem Moderator:
Wunderbar!
Das läuft jetzt schön schnell (ich schaue morgen nochmal, ob es nicht am Cache liegt), aber grob gepeilt benötigt es jetzt nur noch 5% der Zeit, die mein Monsterquery gebraucht hat.
Damit ich jetzt vollends glücklich bin, würde ich noch gerne verstehen was du da eigentlich gemacht hast.
Wo genau liegt der Unterschied von InnerJoin zu LeftJoin? Ich würde mich freuen wenn Du mir den Query erklären würdest :)
 
a LEFT JOIN b
Nimm alles von a und von b dort wo man etwas findet. Das verwendet man wenn a mehr Daten wie b hat und man von a auch die mitausgeben will die kein b-Eintrag enthalten.

a INNER JOIN b
Nimm von a und b nur die Einträge die in beiden Tabellen vorkommen


SQL:
FIELD('suche', a.a, a.b, a.c) != 0
Damit schaue ich ob 'suche' einem der aufgelisteten Feldern entspricht. Wenn ja, wird der Listenindex ausgegeben. Der Rückgabewert 0 besagt dass 'suche' keinem Feld entspreicht

SQL:
        SELECT
            -- Hier war der Hund begraben
            p_all.a_id
            p_all.m_id
        FROM
            a
            INNER JOIN p AS p_select        ON p_select.a_id = a.id
            INNER JOIN p AS p_all           ON p_all.m_id = p_select.m_id
        WHERE
            FIELD('suche', a.a, a.b, a.c) != 0
a wird eigentlich nur fürs Filterkriterium verwendet. Damit gehe ich auf p_select. Damit habe ich die passenden m_id. Um herauszufinden welche Autoren alle mit diesen Büchern zu tun haben muss man über die m_id p nochmals anbinden. Das ist dann p_all. p_all beinhaltet alle user und m_id/a_id Kombinationen die wir bauchen.

Als letzten Schritt noch a und m anhängen um die weiteren Felder rauszukriegen
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück