Самый эффективный способ сделать условное соединение MySQL на несколько таблиц?(Yii php framework) - PullRequest
1 голос
/ 24 июня 2010

У меня есть пять таблиц:

  1. tab_template
  2. template_group
  3. группа
  4. user_group
  5. Пользователь

Tab_template организованы в группы с реляционной таблицей template_group. Пользователи организованы в группы с реляционной таблицей user_group. Группы могут быть общими или частными (используя логический столбец tinyint в таблице).

Я хочу запросить все tab_templates, которые либо:

  1. В той же группе, что и пользователь
  2. или в публичной группе

Вот мой текущий запрос:

ВЫБРАТЬ * ИЗ 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
НА ИСТИНЕ
ГДЕ
group. * * = Тысяча сорок-девять 0
OR
(template_group. group_id = user_group. group_id
И
* * Тысяча пятьдесят восемь. user_id = 2)
GROUP BY t. id;

Это работает, и это не СУПЕР медленно, само по себе, но это отвратительно, как я присоединяюсь к таблице user_group.

Проблема в том, что мне нужно присоединиться к таблице user_group для условной проверки, но мне нужно выполнить эту условную проверку, только если группа не является частной.

Я знаю, что вместо третьего LEFT JOIN с условием ON TRUE я мог бы добавить еще одну таблицу в предложение FROM (FROM tab_template t, user_group ug) ... но я не могу Сделайте это, потому что, как класс Yii ActiveRecord работает с DcCriteria, я не могу изменить эту часть выражения. Я могу редактировать практически любую другую часть запроса, но не предложение FROM. Проверьте API здесь: http://www.yiiframework.com/doc/api/CDbCriteria Так вот почему я присоединяюсь к таблице user_group таким, какой я есть. Некоторые эксперты по Yii могли бы помочь мне решить эту проблему, но я не уверен, что мой запрос будет быстрее, если в любом случае использовать FROM вместо таблиц.

Любая помощь будет принята с благодарностью! Спасибо

Ответы [ 2 ]

1 голос
/ 24 июня 2010

Моя рекомендация для подобных ситуаций - использовать 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

Способ, который легче читать, что облегчает его обслуживание.

0 голосов
/ 24 июня 2010

У меня нет mySql на этой машине, поэтому я не могу проверить это:

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
    )
...