¿Cómo puedo usar alias en la cláusula GROUP BY?

Aquí está mi consulta:

SELECT SUM(score) score, type, context, post_id, e.table_code, comment_id, MIN(seen) seen, MAX(date_time) d_t, (CASE WHEN FROM_UNIXTIME(MAX(date_time)) >= CURDATE() THEN 'today' WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday' WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week' ELSE 'in last month' END) as range_day FROM `events` e WHERE e.id IN ($ids) GROUP BY type, post_id, e.table_code, comment_id, range_day ORDER BY seen, MAX(date_time) desc, MAX(e.id) desc 

Lanza este error:

# 1056 – No se puede agrupar en 'range_day'

Y si range_day de la cláusula GROUP BY , entonces funciona también. Pero también necesito agrupar el resultado basado en range_day . ¿Cómo puedo hacer eso?

No estoy seguro de lo que está tratando de hacer. Pero puede ajustar su consulta en una subconsulta sin range_day en la cláusula GROUP BY. Luego use su cláusula GROUP BY en la consulta externa tal como está.

 SELECT SUM(score) score, type, context, -- WARNING! Not listed in group by clause post_id, table_code, comment_id, MIN(seen) seen, MAX(d_t) d_t, range_day FROM ( SELECT SUM(score) score, MAX(id) as id, type, context, -- WARNING! Not listed in group by clause post_id, e.table_code, comment_id, MIN(seen) seen, MAX(date_time) d_t, (CASE WHEN FROM_UNIXTIME(MAX(date_time)) >= CURDATE() THEN 'today' WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday' WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week' ELSE 'in last month' END) as range_day FROM `events` e WHERE e.id IN ($ids) GROUP BY type, post_id, e.table_code, comment_id ) sub GROUP BY type, post_id, table_code, comment_id, range_day ORDER BY seen, MAX(d_t) desc, MAX(id) desc 

Sin embargo, selecciona context sin agregación que no figura en la cláusula GROUP BY. Por lo tanto, obtendrás un valor "aleatorio" del grupo. En modo estricto, la consulta fallará.

Tu definición de range_day no tiene exactamente sentido. ¿Por qué usa MAX() ? Max de qué?

Una forma natural de hacer que la consulta funcione es eliminar el MAX() de la definición:

 SELECT SUM(score) score, type, context, post_id, e.table_code, comment_id, MIN(seen) as seen, MAX(date_time) as d_t, (CASE WHEN FROM_UNIXTIME(date_time) >= CURDATE() THEN 'today' WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday' WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week' ELSE 'in last month' END) as range_day FROM `events` e WHERE e.id IN ($ids) GROUP BY type, post_id, e.table_code, comment_id, range_day ORDER BY seen, MAX(date_time) desc, MAX(e.id) desc; 

Más comentarios:

  • El IN ($ids) probablemente no haga lo que esperas. Las variables $ids se tratan como un único valor, por lo que esto es equivalente a e.di = $ids .
  • Si esto no hace lo que desea, entonces puede querer MAX() en algún otro nivel de agregación. Eso requeriría una subconsulta adicional.

Primero, tu problema …

No puede agrupar por un agregado. Observe el MAX() dentro de range_day . Su GROUP BY debe include todos los elementos no agregados en SELECT . falta el context y puede dar lugar a un error en versiones posteriores.

Entonces otro problema …

  MIN(seen) seen, MAX(d_t) d_t, ... ORDER BY seen, MAX(d_t) desc 

Observe una incoinheritance? Una ambigüedad? Se seen (en el ORDER BY ) se supone que es el original seen , o el alias seen , lo que significa MIN(seen) ? Lo mismo para d_t ?

Siempre trate de evitar tener un alias deletreado igual al nombre de una columna cuando necesite consultarlo más adelante. En WHERE , debe ser el nombre de la columna; en ORDER BY y HAVING , es el alias.

Entonces, creo , esto es incorrecto: MAX(d_t) desc en el ORDER BY .