2012-04-05 21 views
24

Mi mesa se parece a esto (y estoy usando MySQL):El uso de ORDER BY y GROUP BY junto

m_id | v_id | timestamp 
------------------------ 
6 | 1 | 1333635317 
34 | 1 | 1333635323 
34 | 1 | 1333635336 
6 | 1 | 1333635343 
6 | 1 | 1333635349 

Mi objetivo es tomar cada m_id una vez, y el orden de la más alta marca de tiempo.

El resultado debe ser:

m_id | v_id | timestamp 
------------------------ 
6 | 1 | 1333635343 
34 | 1 | 1333635336 

y escribí esta consulta:

SELECT * FROM table GROUP BY m_id ORDER BY timestamp DESC 

embargo, los resultados son los siguientes:

m_id | v_id | timestamp 
------------------------ 
34 | 1 | 1333635323 
6 | 1 | 1333635317 

creo que provoca, ya que primero hace GROUP_BY y luego ORDEN los resultados.

¿Alguna idea? Gracias.

+2

uso 'MAX' para seleccionar el máximo de su grupo – Nanne

+6

Una cláusula' GRUPO BY' sin función de agregado (por ejemplo: 'COUNT(), SUM(), MAX()') no tiene ningún sentido en absoluto . Me desconcierta que MySQL incluso lo permita. Piénselo, ¿por qué se agrupa si no hace nada con los grupos? – NullUserException

+0

¿Qué pasa si hay dos v_id diferentes para un m_id? ¿Cuál sería el resultado deseado? –

Respuesta

31

Una manera de hacer esto que usa correctamente group by:

select l.* 
from table l 
inner join (
    select 
    m_id, max(timestamp) as latest 
    from table 
    group by m_id 
) r 
    on l.timestamp = r.latest and l.m_id = r.m_id 
order by timestamp desc 

¿Cómo funciona esto:

  • selecciona la última marca de tiempo para cada uno distinto m_id en la subconsulta
  • sólo se selecciona filas de table que coinciden con una fila de la subconsulta (esta operación, donde se realiza una unión, pero no se seleccionan columnas de la segunda tabla, simplemente se usa como filtro) se sabe n como "semijoin" en caso de que tenían curiosidad)
  • ordena las filas
+0

Muchas gracias, está funcionando genial. ¿Puedes explicarme qué es esta la 'r'? es una mesa temporal? ¿cómo llama en SQL? – Luis

+1

@luis - Imagine que la subconsulta es una vista; una vista en línea Necesita un nombre para que pueda consultarlo y sus campos. Esta respuesta le da a la vista en línea el nombre 'r'. Puedes llamarlo casi todo lo que quieras. – MatBailie

+2

@Luis es un alias por el que puede consultar la subconsulta. También podría haber escrito '(seleccionar ...) como r' (tenga en cuenta el as) para hacerlo más claro. –

5

Si realmente no se preocupan por la cual marca de tiempo que obtendrá y su v_id es siempre la misma para un determinado m_i que puede hacer lo siguiente:

select m_id, v_id, max(timestamp) from table 
group by m_id, v_id 
order by timestamp desc 

Ahora bien, si los cambios v_id para un determinado m_id entonces usted debe hacer lo siguiente

select t1.* from table t1 
left join table t2 on t1.m_id = t2.m_id and t1.timestamp < t2.timestamp 
where t2.timestamp is null 
order by t1.timestamp desc 
2

SQL>

SELECT interview.qtrcode QTR, interview.companyname "Company Name", interview.division Division 
FROM interview 
JOIN jobsdev.employer 
    ON (interview.companyname = employer.companyname AND employer.zipcode like '100%') 
GROUP BY interview.qtrcode, interview.companyname, interview.division 
ORDER BY interview.qtrcode; 
3

Puede probar este

SELECT tbl.* FROM (SELECT * FROM table ORDER BY timestamp DESC) as tbl 
GROUP BY tbl.m_id 
+0

No es una buena idea. Está seleccionando todas las filas sin limitación – AliN11

1

Sólo necesito que DESC con asc. Escribe la consulta como a continuación. Devolverá los valores en orden ascendente. SELECCIONAR * FROM table GROUP BY m_id ORDER BY m_id asc;

+0

Eso no funcionará. Si bien revertirá los resultados, todavía no devolverá los resultados deseados. – Richlv

0

Necesita reemplazar DESC con ASC. Escriba la consulta de esta manera y devolverá los valores en orden ascendente.

SELECT * FROM table GROUP BY m_id ORDER BY m_id ASC;