2016-04-07 6 views
1

Почему эти два запроса дают разные результаты для role?Эти 2 SQL-запроса возвращают разные результаты

RIGHT результат (роль по праву ассоциируется с пользователем):

SELECT 
    users.*, 
    activations.id AS activation 
    (SELECT 
     roles.name 
    FROM roles 
    INNER JOIN role_users ON roles.id = role_users.role_id 
    WHERE role_users.user_id = users.id 
    LIMIT 1) AS role 
FROM users 
LEFT JOIN activations ON users.id = activations.user_id 

НЕПРАВИЛЬНО результат (роль всегда первая запись roles таблицы):

SELECT 
    users.*, 
    activations.id AS activation 
    (SELECT 
     roles.name 
    FROM roles 
    INNER JOIN role_users ON roles.id = role_users.role_id 
    INNER JOIN users ON users.id = role_users.user_id 
    LIMIT 1) AS role 
FROM users 
LEFT JOIN activations ON users.id = activations.user_id 

Я не могу использовать первый запрос (с WHERE role_users.user_id = users.id), и я должен использовать второй (с «JOIN»): как добиться правильного результата?

Благодаря

EDIT: ответить на комментарии:

  1. I can't use the first query средства, короче говоря, что я строю его Laravel Query Builder, и выражение WHERE role_users.user_id = users.id, переведенный в ->where('role_users.user_id', '=', 'users.id') в Laravel Query Builder, не работает, потому что он обрабатывается, как если бы он был WHERE role_users.user_id = 'users.id'. Я могу использовать whereRaw(), но я хотел бы избежать этого и искать лучшее решение
  2. Я не создал схему базы данных, но она исходит из Cartalyst Sentinel; это многие-ко-многим, но я забочусь, что каждый пользователь имеет только одну роль, и если пользователь имеет более одной роли, ну, возьмите первый (как там было ORDER BY roles.id)
+4

Что означает 'я не могу использовать первый запрос' ,,, если это дает вам правильный результат, в чем проблема? –

+0

Обратите внимание, что LIMIT без ORDER BY является довольно бессмысленной концепцией. В этом случае я не вижу, что должен делать LIMIT. Короче говоря, если любой запрос возвращает правильный результат, это скорее удача, чем намерение. – Strawberry

ответ

0

Ваш подзапрос не присоединяется к вашему основному запросу, поэтому он не связывает пользователей. Попробуйте это:

SELECT 
     u.*, 
     activations.id AS activation 
     (SELECT 
      roles.name 
     FROM roles 
     INNER JOIN role_users ON roles.id = role_users.role_id 
     INNER JOIN users u1 ON u1.id = role_users.user_id AND u1.id = u.id 
     LIMIT 1) AS role 
    FROM users u 
    LEFT JOIN activations ON u.id = activations.user_id 
+0

Ум ... это имеет смысл, но я получаю «[Err] 1066 - Не уникальная таблица/псевдоним:« пользователи » – Ivan

+0

Отредактирован SQL. Попробуйте еще раз и сообщите мне, если это сработает. – Namrehs

+0

на этот раз я получаю это: '[Err] 1064 - У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с '(SELECT role.name FROM role INNER JOIN role_use' в строке 4' – Ivan

0

Первого запрос вы используете пользователь от внешнего запроса

SELECT 
    /
    (SELECT 
     roles.name 
    FROM roles 
    INNER JOIN role_users ON roles.id = role_users.role_id 
    WHERE role_users.user_id = users.id 
           ^^^^ -- external query user_id 
    LIMIT 1) AS role 
FROM users --- you use this user, so each row has a different user_id 
LEFT JOIN activations ON users.id = activations.user_id 

Второго запрос вы выбираете первую роль из таблицы пользователя, и то же самое для каждой строки.

+0

Есть ли решение для этого? – Ivan

Смежные вопросы