Mysql Запрос с группировкой и join

kznsky

Новичок
Здравствуйте. Нужна помощь.

Есть в базе 2 таблицы. Если упрощенно то:
USER (пользователи) с полями ID, NAME, EMAIL
SCORE (баллы) с полями ID, USER_ID, SCORE, TYPE где score это количество баллов, а type это признак приход или списание баллов (+/-)

Пользователям начисляются баллы или списываются и каждая из этих операций отражается в таблице SCORE с признаком type = "+" или type = "-"

Возникла задача вывести список пользователей с доступными им баллами на сегодня. Это сумма накопленных баллов минус сумма потраченных баллов.
Сейчас я считаю Накопленные баллы и отнимаю от них Потраченные для каждого отдельно взятого пользователя.

Как это сделать одним запросом сразу для всех пользователей?
 
Последнее редактирование:

Valick

Новичок
Группировка по USER_ID и TYPE , агрегат SUM(SCORE) получишь количество начисленных и списанных баллов по каждому пользователю.
 

kznsky

Новичок
Сделал таким запросом:

Код:
SELECT `users`.`id`, `users`.`name`, `users`.`email`,
(tb1.`scorePlus` - tb2.`scoreMinus`) as scoreAvailable
FROM `users`

LEFT JOIN (
    SELECT user, SUM(`score`) AS scorePlus FROM `user_score`
                    WHERE `date` < NOW() - INTERVAL 14 DAY
                        AND `type` = "+" GROUP BY user
) tb1 ON tb1.user = users.id

LEFT JOIN (
    SELECT user, SUM(`score`) AS scoreMinus FROM `user_score`
                    WHERE `type` = "-" GROUP BY user   
) tb2 ON tb2.user = users.id

WHERE 1

Сильно ужасно?
 

WMix

герр M:)ller
Партнер клуба
проверить не могу, но я приблизительно так бы решил
SQL:
select u.id, u.name, u.email, sum(if(us.type='+',us.score,-us.score)) as scoreAvailable
from users u
left join user_score us on u.id=us.user -- возможно left лишний
where us.date < NOW() - INTERVAL 14 DAY -- это можно в ON перенести если пользователи без score также необходимы
group by u.id
сделай пример тут, поправлю
 
Последнее редактирование:

AnrDaemon

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

kznsky

Новичок
проверить не могу, но я приблизительно так бы решил
SQL:
SELECT `users`.`id`, `users`.`name`, `users`.`email`, sum(if(us.type='+',us.score,-us.score)) as scoreAvailable
FROM `users`
LEFT JOIN user_score us ON us.user = users.id
WHERE us.date < NOW() - INTERVAL 14 DAY
GROUP BY users.name
ORDER BY scoreavailable Desc
Сделал так. Спасибо! Все получилось! Менять знак по условию элегантное решение.
Но как быть если начисления становятся активными только через 14 дней и именно поэтому тут условие
us.date < NOW() - INTERVAL 14 DAY
А вот списание учитывается сразу.
По вашему коду и начисление и списание первые 14 дней не учитываются.
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Уточнить условие. Where us.type = ‘-‘ or us.date..., или как там надо.
 
Сверху