MySQL - группировка по неагрегированному столбцу

0

Если я буду хранить свои оценки пользователей так:

+---------+-------+------------+
| user_id | score | created_at |
+---------+-------+------------+
|       1 |   100 | 2017-12-20 |
|       1 |   200 | 2017-12-21 |
|       2 |   110 | 2017-12-20 |
|       2 |   210 | 2017-12-21 |
|       3 |   120 | 2017-12-20 |
|       3 |   220 | 2017-12-21 |
+---------+-------+------------+

Как я смогу получить самую близкую запись для каждого пользователя с датой ввода?

Я дошел до

SELECT *, (abs(datediff("$some-input-date", created_at))) as diff FROM table order by diff

Что дало бы мне дату ввода 2017-12-19:

+---------+-------+------------+------+
| user_id | score | created_at | diff |
+---------+-------+------------+------+
|       1 |   100 | 2017-12-20 |    1 |
|       2 |   110 | 2017-12-20 |    1 |
|       3 |   120 | 2017-12-20 |    1 |
|       1 |   200 | 2017-12-21 |    2 |
|       2 |   210 | 2017-12-21 |    2 |
|       3 |   220 | 2017-12-21 |    2 |
+---------+-------+------------+------+

Теперь мне нужны уникальные строки по user_id, поэтому я предположил, что что-то вроде GROUP BY user_id будет работать, но я получаю сообщение "Выражение SELECT в выражении GROUP BY" в MySQL 5.7. Как я могу группировать user_id в этом сценарии?

(Я также использую доктрину, поэтому, если есть какой-то способ достичь этого, используя функции dql или доктрины, которые также будут полезны)

Теги:
doctrine
doctrine2

1 ответ

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

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

SELECT * FROM
--your current query
(SELECT *, (abs(datediff("$some-input-date", created_at))) as diff FROM table) as data_with_diffs
INNER JOIN
( --a query to find only the minimum diffs per user id
 SELECT userID, MIN(abs(datediff("$some-input-date", created_at))) as min_diff 
 FROM table 
 GROUP BY userid
) as find_min_diffs

ON 
  data_with_diffs.userid = find_min_diffs.userid AND
  data_with_diffs.diff = find_min_diffs.min_diff

Если вы выполняете два внутренних запроса в отдельности, вы увидите, как это работает. Есть и другие способы структурирования этого, но я подумал, что было бы лучше, если бы вы увидели, как все это висит вместе на основе того, что вы не понимаете/уже разработали

Запрос группировки выбирает только минимальный diff для определенного идентификатора пользователя. Запустив это как подзапрос и присоединив его к уже полученным данным, INNER JOIN будет отфильтровывать все строки, где diff не равен минимальной разности

Вы можете по-прежнему получать повторяющиеся строки для пользователя, если у них есть дата до и дата после с тем же разным (т.е. -1 и +1 - они являются ближайшими), поэтому вам, возможно, придется реализовать стратегию для решения что, как и выбор их MAX-оценки

Ещё вопросы

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