Moyen le plus efficace de faire un mysql conditionnel se joindre à plusieurs tables? (Php cadre Yii)
-
29-09-2019 - |
Question
J'ai cinq tableaux:
- tab_template
- template_group
- groupe
- groupe_de_l_utilisateur
- utilisateur
de Tab_template sont organisés en groupes avec la table relationnelle template_group. sont organisés en groupes avec la table relationnelle groupe_de_l_utilisateur ses utilisateurs. Groupe de peut être public ou privé (à l'aide d'une colonne tinyint booléenne dans le tableau).
Je veux requête pour tous les tab_templates qui sont soit:
- Dans le même groupe que l'utilisateur
- Ou dans un groupe public
Voici ma requête en cours:
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
OÙ
group
.private
= 0
OU
(template_group
.group_id
= user_group
.group_id
ET
user_group
.user_id
= 2)
GROUP BY t
.id
;
Il fonctionne, et ce n'est pas lent SUPER en soi, mais il est hacky la façon dont je me joins à la table groupe_de_l_utilisateur.
Le problème est que je dois joindre à la table de groupe_de_l_utilisateur pour un contrôle conditionnel, mais je ne dois faire que l'enregistrement conditionnel si le groupe n'est pas privé.
Je sais qu'au lieu de la troisième LEFT JOIN avec la condition ON vrai que je pourrais ajouter une autre table à la clause FROM (DE tab_template
de t
, user_group
ug
) ... mais je ne peux pas le faire parce que la façon dont la classe ActiveRecord de Yû travaille avec I DcCriteria ne peuvent pas modifier cette partie de la déclaration. Je peux modifier à peu près tout autre partie de la requête, mais pas la clause FROM. Consultez l'API ici: http://www.yiiframework.com/doc/api/CDbCriteria Voilà pourquoi je rejoins la table groupe_de_l_utilisateur la façon dont je suis. Certains experts Yii pourraient être en mesure de me aider à résoudre ce problème, mais je ne suis pas sûr que ma requête sera plus rapide par FROMing les tables au lieu de se joindre à eux en tout cas.
Toute aide serait grandement appréciée! Merci
La solution
Ma recommandation pour des situations comme celles-ci est d'utiliser une 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
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
Chemin plus facile à lire, ce qui le rend plus facile à maintenir.
Autres conseils
Je n'ai pas mySql sur cette machine, donc je ne peux pas tester ceci:
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
)