2013-06-27 3 views
3

У меня 3 таблицы (важно только для вопросительных колонн здесь):MySQL: пользователи, users_groups и Grous таблицы

USERS    GROUPS     USERS_GROUPS 
id     id      user_id 
        importance    group_id 
        color     

Как вы можете видеть, один пользователь может быть во многих группах, каждая группа имеет разные цвет, некоторые группы важнее других. Например, пользователь А находится в группе редактор (синий цвет) и модератор (зеленый цвет). Какой цвет он должен быть видимым? В зеленом цвете, потому что модератор более важен, чем редактор.

Но я понятия не имею (возможно, это невозможно в одном запросе?) Как получить цвет пользователя из групп групп. я создал такой запрос:

SELECT * FROM `users` INNER JOIN users_groups ON users_groups.user_id = users.id INNER JOIN groups ON groups.id=users_groups.group_id 

Но он возвращает строки, как много пользователя, как пользователь имеет группу, как это:

USERNAME (...) GROUP_ID  NAME (group)   COLOR  IMPORTANCE 
user    2    moderator   green  50 
user    3    editor    blue  25 
administrator  1    admin    orange  100 
administrator  3    editor    blue  25 

Я хотел бы получить только самую важную группу - администратор в качестве члена администратор группы и пользователь в качестве члена модератора группы.

ответ

1

Вариант 1: Это один получает наиболее важную группу для каждого пользователя, а затем возвращается в groups таблицу, чтобы найти цвет для этой группы. Дополнительный JOIN необходим, потому что исходная GROUP BY не обязательно получит правильный цвет, соответствующий результату MAX (важность).

SELECT T1.*, groups.color FROM 
(
    SELECT users.id, MAX(groups.importance) AS most_important_group FROM `users` 
    INNER JOIN 
    users_groups 
    ON users_groups.user_id = users.id 
    INNER JOIN groups 
    ON groups.id=users_groups.group_id 
    GROUP BY users.id 
) AS T1 
INNER JOIN 
groups 
ON T1.most_important_group=groups.importance 
GROUP BY T1.id 

Вариант 2: Эта опция упорядочивает первоначальный результат устанавливается таким образом, который должен принести друг пользователей наибольшее значение группу на вершину вместе с соответствующим цветом из этой строки. После внешней GROUP BY вы должны видеть только одну строку для каждого пользователя, содержащего требуемую информацию. Вы можете настроить, какие поля возвращать из подзапроса. Я включил как можно больше, но вы должны уничтожить их, если они вам не нужны (меньшее количество полей должно означать более быстрый результат).

SELECT * FROM 
(
    SELECT users.*, users_groups.*, groups.importance, groups.color FROM `users` 
    INNER JOIN users_groups 
    ON users_groups.user_id = users.id 
    INNER JOIN groups 
    ON groups.id=users_groups.group_id 
    ORDER BY users.id, groups.importance DESC 
) AS T1 
GROUP BY T1.id 

Эксплуатационные характеристики этих изделий будут различаться в зависимости от размеров стола и определенно с вашей структурой индекса. Попробуйте их обоих и ответьте, с какой скоростью. Если вам требуется более быстрое время работы, не стесняйтесь отвечать некоторыми операторами EXPLAIN из этих запросов и инструкциями DESCRIBE о таблицах.

1

Это довольно распространенная проблема в mysql, которая имеет несколько различных решений, в целом наиболее быстрый - это присоединиться к подзапросу, который выбирает самое большое значение для фильтрации результатов.

SELECT users.*, groups.* 
FROM `users` 
INNER JOIN users_groups 
ON users_groups.user_id = users.id 
INNER JOIN groups 
ON groups.id=users_groups.group_id 
INNER JOIN (SELECT user_groups.user_id, MAX(importance) AS importance FROM groups GROUP BY user_id) mxGrp 
ON (groups.user_id = mxGrp.user_id AND groups.importance = mxGrp.importance); 

Читать this blog post для обсуждения других возможных решений.

+0

Благодарим за ссылку – Andy