Zum Inhalt springen

SQL Frage zu MM Tabellen

Erstellt am 31. Juli 2007 · 14 Antworten · letzte Antwort am 2. August 2007

Tags: Frage

Winddancer ·

Hallo Leute,

ich habe eine (hoffentlich) simple Frage zu einer SQL Query.

Ich habe in einer Extension zwei Tabellen.

Eine Tabelle cd.
uid, title, cat, description

Eine Tabelle cd_Kategorie
uid, title

Eine m:m Tabelle cd_Kategorie_mm
uid_local, uid_foreign, tablenames, sorting

Standard typo3 Setup ebend. Meine Abfragen funktionieren ganz hervorragend, wenn ich sie mit OR schreibe. Heisst, wenn ich meine Plugin sage: Zeige mir alle CDs die mind. eine der ausgewählten Kategorien haben.

beispiel:

SELECT title 
FROM cd 
INNER JOIN cd_Kategorie ON cd_Kategorie_mm.uid_foreign = cd_Kategorie.uid 
LEFT JOIN cd_Kategorie_mm ON cd.uid = cd_Kategorie_mm.uid_local 
WHERE cd_Kategorie_mm.uid_foreign = 4 OR cd_Kategorie_mm.uid_foreign = 5

Das gibt mir alle CD Titel mit der Kategorie 4 ODER 5 aus.

Ich möchte nun alle CD Titel haben, die sowohl Kategorie 4 UND 5 sind.

Das OR mit AND ersetzen liefert keinen Rückwert. Was ja auch eigentlich logisch ist. Weil ja für jede Kategorie ein eigner Wert existiert...

Wie kann ich das mit einer Query hinbekommen!? Mit einer subquery!?

steffenk ·

Du brauchst keine Subquery, noch nichtmal Deine joins - es gibt Typo3-Funktionen dafür:

$res=$GLOBALS['TYPO3_DB']->exec_SELECT_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='');
Winddancer ·

Danke für den Hinweis! Das werde ich mir gleich mal zu Gemüte führen.

Woher weiss man sowas? Wieso finde ich das nie in den Dokus!? :/

Winddancer ·

so... habe mir die Funktion gerade mal angeguckt und muss sagen, dass die ja echt mal Müll zusammenbaut. Jetzt weiss ich auch wieso tt_news darauf verzichtet hat.
Ohne vernünftige Distinct Anweisungen geht da mal garnichts.

Ich bin eigentlich ein großer Verfechter von Joins, weil die Ergebnisse einfach und sauber sind.

Ich glaube ich nehme doch lieber die normale exec_SELECTquery und baue noch weiter an meinen mysql Statement.

oh und außerdem löst es mein Problem leider auch nicht.

Das ist nur eine andere Weise Querys zu schreiben, die zwar einfacher ist wenn man nicht über viele sql Kenntnisse verfügt, aber nicht unbedingt eine gute Query hervorbringt.

steffenk ·

gut gebrüllt Löwe - aber auch diese Funktion baut Joins, nur keine Left.
Und richtig eingesetzt funktioniert das schon, wenn ich was Zeit hätte würde ich Dir das beispiel zeigen.

Aprospos Doku: im ersten Thread sind alle Links drin, und eine Offlinedoku hast Du mit extdeveval.

Und Distinct: geht in der serlect-Anweisung

und tt_news:

	// get categories from the tt_news record in db
				$res = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query ('tt_news_cat.uid,tt_news_cat_mm.sorting AS mmsorting', 'tt_news', 'tt_news_cat_mm', 'tt_news_cat', ' AND tt_news_cat_mm.uid_local='.(is_int($fieldArray['l18n_parent'])?$fieldArray['l18n_parent']:$id).t3lib_BEfunc::BEenableFields('tt_news_cat'));
Winddancer ·

ich hoffe Du hast das nicht falsch verstanden! Bin wirklich für jeden Tipp dankbar und finde es auch gut, dass man hier mittlerweile so schnell ne Antwort bekommt! Finde ich klasse!

Ich meinte bloss, dass ich den Aufbau nicht optimal finde.

Habe mich jetzt mal weiter durch die SQL Doku gelesen und so gehts:

...
WHERE cd.uid
IN (
SELECT uid_local
FROM cd_Kategorie_mm
WHERE uid_foreign
IN ( 4,5 )
GROUP BY uid_local
HAVING count( * ) =2
)
...
Winddancer ·

Nur noch eine Frage: Wo kann ich in der exec_SELECT_mm_query Joins einbauen? Mal von den manuellen Möglichkeiten abgesehen (so wie ich es bei der normalen query gemacht habe).

Wenn ich die Parameter der Funktion nutze macht er jedenfalls keine Joins draus, sondern setzt das in die where Bedingung um. :/

steffenk ·

ich habe nichts falsch verstanden, ich wollte Dir nur wiederlegen was Du behauptet hattest.

Sicherlich verdienen die erzeugten Queries keinen Schönheitspreis, aber sie zu nutzen hat gute Gründe:
Die TYPO3-API ist flexibel und über DBAL kompatibel zu beliebigen DB-Engines. Daher ist es ratsam (und gehört zu den TYPO3 Coding-Guidelines) sie zu nutzen.
Durch direkte SQL-Queries hebelst Du das aus.

Sicher gibt es Situationen, die einem keine Wahl lassen, aber bei Deiner Aufgabenstellung sollte das schon gehen, auch wenns kniffelig ist 😉

Winddancer ·

Ok ist ein Argument...

Aber sobald ich die von mir vorgeschlagene Subquery nutze, bin ich ja eh wieder von der Dbal Möglichkeit weg oder?

steffenk ·

ja - in dem Moment schon wo Du "SQL"-Anweisungen nutzt, dann kann die Query nicht mehr logisch zerlegt werden.

zu Deiner Ursprungsfrage: Alle die entweder 4 oder 5 als Kategorie haben:
where (cd_Kategorie.uid=4 OR cd_Kategorie.uid=5)

Also sollte es so schon gehen:

$res=$GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
'cd.*,cd_Kategorie.cat',
'cd',
'cd_Kategorie_mm',
'cd_Kategorie',
'(cd_Kategorie.uid=4 OR cd_Kategorie.uid=5) '.$this->cObj->enableFields('cd'),
'',
'cd_Kategorie.cat,cd.sorting',
'');
Winddancer ·

Hallo nochmal,

ja, das entweder oder ging schon.

Mein Problem lag darin alle CDs zu finden, die Kategorie 4 UND 5 haben. Und das ist mit einem normalen AND leider nicht getan, da es ja zwei Datensätze sind.

Jetzt musste ich bloss leider feststellen, dass subqueries mit typo3 nicht gehen. Zumindest nicht wie ich es eingebunden haben (einfach in die WHERE Bedingung).

Wenn ich den query debuggen lasse und das ganze direkt abfrage, bekomme ich schön alle CDs mit Kategorie 4 und 5. (also die beiden Kategorien haben).

Wenn ich die normal via typo3 bearbeite (also via exec_SELECT_query) bekomme ich nur eine ungültige mysql ressource Meldung. :/

Also doch lieber Dein Vorschlag, damit bleibe ich dann wenigstens den Coding Guidelines treu. Werde ich das wohl irgendwie anders abfedern müssen...

Ich werde mir morgen nochmal tt_news anschauen, die machen ja auch das gleiche.

Oder hast Du vielleicht noch eine Idee wie man meine subquery (s.o.) typo3 konform einbauen kann?

Danke nochmal für Deine Hilfe.

steffenk ·

wenn Du aus dem OR ein AND machst, solltest Du alle CD's bekommen, die beide Kategorien haben - getestet ?

Winddancer ·

Ja habe ich. Und es funzt leider nicht.

Ich bin jetzt schon wieder auf eine andere Problematik gestoßen bzgl. exec_SELECT_mm_query. Ich kann die Abfrage immer nur mit einer MM Tabelle machen oder?

Ich müsste aber in mehreren Beispielen 3 bis 4 Tabellen abfragen. Mit Joins könnte ich die aneinander hängen, aber soweit ich das der Beschreibung der Funktion entehmen kann (und nach eigenen Tests) geht das nur mit einer Tabelle.

Oder gibt es da eine Option / Feature etc. was ich mal wieder übersehen habe?

siehe hier: http://typo3.org/fileadmin/typo3api-3.8.0/de/d07/classt3lib__DB.html#a4

steffenk ·

mit Hilfe von Inner Joins kannst Du beliebig viele Tabellen benutzen, nicht aber mit der mm_query, da die immer nur 3 tabellen berücksichtigt.

Inner Join:

Select ... from table_a a,table_b b,table_c c,table_d d
where (b.uid=a.feldb and c.uid=a.feldc...)

Winddancer ·

jap. So hatte ich mir das auch schon gedacht. Damit bleibt ja auch die DBAL Kompatibilität erhalten.

Aber besser fragen als wieder was zu übersehen! 😉