2013-02-19 5 views
0

У меня есть две таблицы: users и changes. Я хочу отслеживать количество изменений, которые каждый пользователь делает. В настоящее время я делаю это в двух отдельных отчетах в сочетании с PHP:LEFT JOIN не совсем работает

// Get all users 
$stmt = GlobalContainer::$dbh->prepare("SELECT 
     id, username, realname 
    FROM 
     users 
    ORDER BY role_id, realname"); 
$stmt->execute(); 
while ($user = $stmt->fetch()) { 
    $users[$user['id']] = $user; 
    $users[$user['id']]['changes'] = 0; 
} 

// Get number of changes for each user 
$stmt = GlobalContainer::$dbh->prepare("SELECT COUNT(*) AS `count`, user_id 
    FROM 
     changes 
    GROUP BY user_id"); 
$stmt->execute(); 
while ($changes = $stmt->fetch()) { 
    $users[$changes['user_id']]['changes'] = $changes['count']; 
} 

Это прекрасно работает, но я думаю, что это было бы аккуратнее, если я соединил его в одном запросе. Это то, что у меня есть:

SELECT 
     users.id, users.username, users.realname, count(changes.user_id) as `count` 
    FROM 
     users 
    LEFT JOIN `changes` ON users.id = changes.user_id 
    GROUP BY user_id 
ORDER BY `count` ASC 

Однако по какой-то причине он пропускает все, кроме одного из пользователей с 0 изменениями, даже если существует несколько. Есть также несколько пользователей, которые имеют по 3 изменения, и все они отображаются правильно. Как я могу заставить этот запрос работать, чтобы он показывал всем пользователям с 0 изменениями?

+0

Можете ли вы опубликовать данные? Не понял, что вы имеете в виду, показывая пользователю с 0 изменениями. – DevelopmentIsMyPassion

+0

changes.user_id вернется в нуль, если в этой таблице нет соответствующих записей. Иногда nulls испортит агрегаты, такие как COUNT(). Вы можете попробовать заменить нуль нулем внутри COUNT(). – criticalfix

+0

Кажется, это исправить: 'GROUP BY users.id' вместо' GROUP BY changes.user_id'. Может быть, кто-то может написать ответ, объясняющий * почему *, потому что я действительно не знаю. – Mike

ответ

3

Ну, похоже, недавно удаленный ответ был правильным. Вот разбивка (и demo). Первоначальный запрос состоял в группировке nulls в один результат. Легким ответом является группировка по значению, которое не является нулевым. Это делает окончательный запрос таким образом:

SELECT 
     `users`.id, `users`.username, `users`.realname, count(changes.user_id) as `count` 
    FROM 
     `users` 
    LEFT JOIN `changes` ON users.id = changes.user_id 
GROUP BY `users`.id; 
+0

справа из-за левого объединения - значения в таблица изменений МОЖЕТ быть нулевой, хороший улов. – Hituptony

+0

Надеюсь, я не наступаю на чьи-то пальцы, повторно отправляя проголосовавший ответ –

+0

Я согласен - удалил свой ответ, когда он был опущен, чтобы рассмотреть вопрос, поскольку, как я думал, я мог бы его неправильно понять. – dugas

1

Изменить группу, чтобы:

GROUP BY users.id 
+0

+1 у вас было это сначала :) –

0
SELECT users.id, users.username, users.realname, count(changes.user_ID) from `changes` as `count` from users 
left join `changes` on users.id = changes.user_id 
group by users.id; 

Ваш счетчик сбросив свои результаты, вы можете гнездо, что в подзапрос, чтобы исключить его из вашей левой присоединиться, который в свою очередь только возвращающие строки где count (changes.user_id) и объединение их в одну запись. Если вы используете подзапрос, вы можете эффективно получить счетчик изменений.user_id, не выполняя левое соединение.

+0

, если вы обнаружите, что подзапрос возвращает те же результаты. Я стою исправлено. – Hituptony

+0

Это фактически возвращает одно и то же значение для каждого пользователя. Похоже, что сумма из всех строк. – Mike

+0

Спасибо за ваш ответ. Я отредактировал свой ответ. – Hituptony

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