Выражение не входит в предложение GROUP BY - PullRequest
0 голосов
/ 24 сентября 2018

У меня есть таблица журналов в MySQL (v5.7), в которой записываются запросы пользователей, из которых я извлекаю разбивку действий с указанием количества пользователей и общего количества посещений за каждый месяц, например:

Date            Users   Hits
September 2018  20      1,839
August 2018     23      2,723
July 2018       21      1,632
June 2018       22      2,981

Этов настоящее время достигается с помощью следующего запроса:

SELECT month(l.time) m, year(l.time) y, date_format(l.time, '%M %Y') monthyear, 
  (select count(distinct userid) from log lm 
    where month(lm.time) = month(l.time) and year(lm.time) = year(l.time)) users,
  count(u.name) hits
FROM log l left join users u on u.id=l.userid
group by date_format(l.time, '%M %Y')
order by l.time desc, l.id desc

Этот SQL завершается ошибкой с включенным only_full_group_by, как это теперь по умолчанию в MySQL, поскольку не все выражения содержатся в предложении GROUP BY.Решения, которые я нашел, обычно включают использование агрегатной функции, такой как MAX (), или добавление всех выражений в предложение GROUP BY, но подзапрос 'users' делает эти подходы проблематичными: я не могу использовать подход MAX () (неверный синтаксис) и добавление его в предложение GROUP BY приводит к такому медленному запросу, что я еще не видел завершенный тест.

Я чувствую, что, возможно, есть элегантное и производительное решение, не прибегающее к отключению only_full_group_by,но я не в своей глубине с SQL.

Ответы [ 2 ]

0 голосов
/ 24 сентября 2018

Вот упрощенный запрос:

SELECT DATE_FORMAT(l.time, '%M %Y') AS monthyear, 
  COUNT(DISTINCT l.userid) AS users,
  COUNT(*) AS hits
FROM log l
GROUP BY monthyear

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

Вам вообще не нужно присоединяться к таблице users, если только вы не хотите считать только попадания пользователей с столбцом, отличным от NULL name (COUNT игнорирует NULL, и я думаю, вы хотите подсчитать все попадания изжурнал, что означает, что вы должны использовать COUNT(*) вместо COUNT(u.name).

Я удалил предложение ORDER BY, потому что оно ссылается на столбцы, которых нет в результате. Если вы хотите сделать заказ по месяцу,вам следует подумать о форматировании месяца в том виде, в каком вы хотите, таким образом:

SELECT DATE_FORMAT(l.time, '%Y-%m') AS monthyear, 
  COUNT(DISTINCT l.userid) AS users,
  COUNT(*) AS hits
FROM log l
GROUP BY monthyear

По умолчанию GROUP BY упорядочит группы по значению.

0 голосов
/ 24 сентября 2018

Я не уверен, почему вы хотите использовать подзапрос для этого.Разве это не делает то, что вы хотите?

SELECT month(l.time) as m, year(l.time) as y, date_format(l.time, '%M %Y') as monthyear, 
       count(distinct l.userid) as users,
       count(u.name) as hits
FROM log l left join
     users u
     on u.id = l.userid
GROUP BY m, y, monthyear
ORDER BY max(l.time) desc, l.id desc;
...