Considere una tabla que registra las visitas
create table visits (
  person varchar(10),
  ts timestamp, 
  somevalue varchar(10) 
)Considere estos datos de ejemplo (marca de tiempo simplificada como contador)
ts| person    |  somevalue
-------------------------
1 |  bob      |null
2 |  bob      |null
3 |  jim      |null
4 |  bob      |  A
5 |  bob      | null
6 |  bob      |  B
7 |  jim      |  X
8 |  jim      |  Y
9 |  jim      |  nullEstoy tratando de llevar el último valor no nulo de la persona a todas sus visitas futuras hasta que ese valor cambie (es decir, se convierta en el siguiente valor no nulo).
El conjunto de resultados esperado se ve así:
ts|  person   | somevalue | carry-forward 
-----------------------------------------------
1 |  bob      |null       |   null
2 |  bob      |null       |   null
3 |  jim      |null       |   null
4 |  bob      |  A        |    A
5 |  bob      | null      |    A
6 |  bob      |  B        |    B
7 |  jim      |  X        |    X
8 |  jim      |  Y        |    Y
9 |  jim      |  null     |    YMi intento se ve así:
 select *, 
  first_value(somevalue) over (partition by person order by (somevalue is null), ts rows between UNBOUNDED PRECEDING AND current row  ) as carry_forward
 from visits  
 order by tsNota: el (algún valor es nulo) se evalúa a 1 o 0 con el propósito de ordenar para que pueda obtener el primer valor no nulo en la partición.
Lo anterior no me da el resultado que busco.
                    
                        postgresql
                                window-functions
                                
                    
                    
                        maxTrialfire
fuente
                
                fuente

pg_dumpdatos de prueba en lugar de pegar los datos en una salida psql y el esquema de la tabla?pg_dump -t table -d databaseNecesitamos la creación y losCOPYcomandos.Respuestas:
La siguiente consulta logra el resultado deseado:
Tenga en cuenta la declaración de caso nulo: si IGNORE_NULL fuera compatible con las funciones de la ventana de postgres, esto no sería necesario (como lo menciona @ ypercubeᵀᴹ)
fuente
count(somevalue) over (...)El problema está en la categoría de problemas de brechas e islas. Es una pena que Postgres aún no haya implementado
IGNORE NULLen funciones de ventana comoFIRST_VALUE(), de lo contrario, sería trivial, con un simple cambio en su consulta.Probablemente hay muchas maneras de resolver esto utilizando funciones de ventana o CTE recursivos.
No estoy seguro de si es la forma más eficiente, pero un CTE recursivo resuelve el problema:
fuente