Effizienteste Weg, eine bedingte mysql verbindet auf mehreren Tabellen zu tun? (Yii PHP-Framework)
-
29-09-2019 - |
Frage
Ich habe fünf Tabellen:
- tab_template
- template_group
- Gruppe
- user_group
- Benutzer
sind Tab_template die in Gruppen organisiert, mit der template_group relationalen Tabelle. Benutzer des mit der user_group relationalen Tabelle in Gruppen organisiert. Gruppe kann öffentlich oder privat sein (eine Tinyint boolean Spalte in der Tabelle verwendet wird).
Ich möchte Abfrage für alle die tab_templates, die entweder:
- In der gleichen Gruppe wie der Benutzer
- oder in einer öffentlichen Gruppe
Hier ist meine aktuelle Abfrage:
SELECT * FROM tab_template
t
LEFT JOIN template_group
ON template_group
.tab_template_id
= t
.id
LEFT JOIN group
ON template_group
.tab_template_id
= group
.id
LEFT JOIN user_group
ON TRUE
WO
group
.private
= 0
OR
(template_group
.group_id
= user_group
.group_id
UND
user_group
.user_id
= 2)
GROUP BY t
.id
;
Es funktioniert, und es ist nicht super langsam per se, aber es ist Hacky die Art, wie ich in dem user_group Tisch kommen.
Das Problem ist, dass ich die user_group Tabelle für einen bedingten Scheck JOIN, aber ich brauchte nur den bedingten Scheck zu tun, wenn die Gruppe nicht privat ist.
Ich weiß, dass anstelle des dritten LEFT JOIN mit der TRUE Zustand ON ich eine andere Tabelle der FROM-Klausel (FROM tab_template
t
, user_group
ug
) hinzufügen könnte ... aber ich kann das nicht tun, weil die Art und Weise Yü der Klasse Active Arbeiten mit dem DcCriteria kann ich nicht, dass ein Teil der Aussage ändern. Ich kann fast jeden anderen Teil der Abfrage bearbeiten, aber nicht die FROM-Klausel. Schauen Sie sich die API hier: http://www.yiiframework.com/doc/api/CDbCriteria ist also, warum ich die Art und Weise der user_group Tisch bin Joining ich bin. Einige Yü Experten könnten in der Lage sein, mir zu helfen, dieses Problem zu lösen, aber ich bin nicht sicher, ob meine Abfrage wird schneller durch froming der Tabellen statt dem Joining sie trotzdem.
Jede Hilfe wäre sehr dankbar! Dank
Lösung
Meine Empfehlung für Situationen wie diese ist eine UNION zu verwenden:
SELECT t.*
FROM TAB_TEMPLATE t
JOIN TEMPLATE_GROUP tg ON tg.tab_template_id = t.id
JOIN GROUP g ON g.id = tg.tab_template_id
AND g.private = 0
UNION
SELECT t.*
FROM TAB_TEMPLATE t
JOIN TEMPLATE_GROUP tg ON tg.tab_template_id = t.id
JOIN GROUP g ON g.id = tg.tab_template_id
AND g.private != 0
JOIN USER_GROUP ug ON ug.group_id = g.id
Weg leichter zu lesen, das macht es leichter zu pflegen.
Andere Tipps
Ich habe mySql nicht auf dieser Maschine, so kann ich diese nicht testen:
SELECT
TT.col1,
TT.col2,
...
FROM
Tab_Templates TT
WHERE
EXISTS
(
SELECT *
FROM
Template_Groups TG
WHERE
TG.tab_template_id = TT.id AND
TG.private = 0
) OR
EXISTS
(
SELECT *
FROM
User_Groups UG
INNER JOIN Template_Groups TG2 ON
TG2.tab_template_id = TT.id AND
TG2.group_id = UG.group_id
WHERE
UG.user_id = 2
)