2011-09-30 18 views
10

Tengo una tabla simple con un unit_id oid, indicación de fecha y hora, diag bytea. La clave principal es una combinación de tiempo y unit_id.Postgres selecciona todas las columnas pero agrupa por una columna

La idea detrás de esta consulta es obtener la última fila (marca de tiempo más grande) para cada unit_id único. Sin embargo, las filas para cada unit_id con la última hora no siempre se devuelven.

Realmente quiero agrupar solo unit_id, pero postgres me hace usar diag también, ya que estoy seleccionando eso.

SELECT DISTINCT ON(unit_id) max(time) as time, diag, unit_id 
FROM diagnostics.unit_diag_history 
GROUP BY unit_id, diag 

Respuesta

14

Cada vez que usted comienza a pensar que quiere un grupo localizado POR usted debe empezar a pensar en window functions lugar.

creo que lo que busca es algo como esto:

select unit_id, time, diag 
from (
    select unit_id, time, diag, 
      rank() over (partition by unit_id order by time desc) as rank 
    from diagnostics.unit_diag_history 
) as dt 
where rank = 1 

Es posible que desee añadir algo a la ORDER BY para romper constantemente los lazos tan bien pero que no alteraría la técnica en general.

+0

¿Podemos hacer esto sin usar sub selección? – metdos

+0

@metdos: No puedo pensar en nada fuera de mi cabeza, pero podría haber una manera. ¿Qué pasa con las tablas derivadas? –

9

Usted puede unirse al selecto agrupado con la tabla original:

SELECT d.time, d.diag, d.unit_id 
FROM(
    SELECT unit_id, max(time) as max_time 
    FROM diagnostics.unit_diag_history 
    GROUP BY unit_id 
) s JOIN diagnostics.unit_diag_history d 
ON s.unit_id = d.unit_id AND s.max_time = d.time 
+0

Esta es la única respuesta que he encontrado en varios días de Google que me ayudó de alguna manera (viniendo de MySQL). – Adrian

Cuestiones relacionadas