Уменьшить количество объединений на одном столе

0

У меня две таблицы:

ranking_history

| user_id | ranking | time
|    1    |  2      | 2018-05-21     
|    1    |  5      | 2018-04-28
|    2    |  9      | 2018-05-21     
|    2    |  1      | 2018-04-28

пользователь

| id | ranking 
| 1  |  7     
| 2  |  3     

Мне нужно присоединиться к этим двум таблицам, чтобы создать таблицу так:

| id | ranking | last_weeks_ranking | last_months_ranking 
| 1  |  7      |     2              |    5  
| 2  |  3      |     9              |    1  

Это то, что я пробовал:

SELECT *, r1.ranking as last_weeks_ranking, r2.ranking as last_months_ranking 
from user 
left join ranking_history r1 on user.id = r1.user_id where r1.time = '2018-05-21' 
left join ranking_history r2 on user.id = r2.user_id where r2.time = '2018-04-28' 

Выход в порядке, но мне нужно присоединиться к одной таблице дважды. Есть ли более простой способ сделать это?

  • 1
    Вы могли бы просто свои данные, исключив специальный случай user.ranking и вместо этого сохраняя текущий рейтинг в ranking_history .
  • 0
    stackoverflow.com/questions/tagged/mysql+pivot
Показать ещё 1 комментарий
Теги:
pivot
join

2 ответа

5
Лучший ответ

Использовать условную агрегацию

  SELECT user.id,
         MAX(user.ranking) as ranking,
         MAX(CASE WHEN r1.time = '2018-05-21' THEN r1.ranking END) as last_weeks_ranking,
         MAX(CASE WHEN r1.time = '2018-04-28' THEN r1.ranking END) as last_months_ranking
  FROM user
  JOIN ranking_history r1 
    ON user.id = r1.user_id 
  GROUP BY user.id
  • 0
    Этот запрос делает именно то, что мне нужно. Спасибо за помощь!
2

Другой подход заключается в использовании связанных друг с другом подзапросов:

SELECT 
   user.id, 
   user.ranking,
   (SELECT 
        ranking_history.ranking 
    FROM 
        ranking_history
    WHERE
        ranking_history.user_id = user.id
        AND ranking_history.time >= NOW() - INTERVAL 1 WEEK - INTERVAL 1 DAY
    ORDER BY 
        ranking_history.time ASC
    LIMIT 1) AS last_weeks_ranking,
   (SELECT 
        ranking_history.ranking 
    FROM 
        ranking_history
    WHERE
        ranking_history.user_id = user.id
        AND ranking_history.time >= NOW() - INTERVAL 1 MONTH - INTERVAL 1 DAY
    ORDER BY 
        ranking_history.time ASC    
    LIMIT 1) AS last_months_ranking    
FROM 
    user

PS: Я добавил динамический расчет даты для столбцов last_weeks_ranking и last_months_ranking вместо этого, используя фиксированные значения "2018-05-21" и "2018-04-28",

Результат

| id | ranking | last_weeks_ranking | last_months_ranking |
+----+---------+--------------------+---------------------+
|  1 |       7 |                  2 |                   5 |
|  2 |       3 |                  9 |                   1 |

см. демо http://sqlfiddle.com/#!9/2f8e2c/9

Ещё вопросы

Сообщество Overcoder
Наверх
Меню