tengo un problema con la agrupacion
Tengo una tabla (muchas más cosas en ella, pero no relevantes) que se parece a:
id user 0 1 1 1 2 1 3 2 4 2 5 2 6 1 7 1Estoy tratando de obtener el siguiente valor:
user start end 1 0 2 2 3 5 1 6 7Básicamente, necesito la primera y la última aparición del usuario, sin alterar el orden. Sé que necesito usar OVER (PARTITION BY...), pero nunca lo he usado y no estoy seguro de cómo crear esta consulta. si "particiono por usuario", ignora el pedido. Y si "particiono por id, usuario" vuelve a ser incorrecto.
Ejemplo de lo que intenté (ni siquiera intenta obtener lo que necesito, pero es un punto medio que me muestra cómo hacerlo una vez que descubro la parte "superior"):
SELECT user, count(user) over (partition by user): user count 1 5 1 5 1 5 2 3 2 3 2 3 1 5 1 5 SELECT user, count(user) over (partition by id, user): user count 1 1 1 1 1 1 2 1 2 1 2 1 1 1 1 1Use un enfoque de diferencia de números de fila para clasificar filas consecutivas con el mismo usuario en un grupo y comience de nuevo un nuevo grupo cuando se encuentre un nuevo usuario. A partir de entonces, use group by para obtener el inicio y el final de cada grupo.
SELECT USER,MIN(ID) AS START,MAX(ID) AS END FROM (SELECT user,id, row_number() over(order by id) - row_number() over (partition by user order by id) as grp FROM tablename ) T GROUP BY USER,GRPpara obtener inicio, final de id, use:
SELECT user, min(id) over (partition by user) "start", max(id) over (partition by user) "end" from table_name;Actualizar Mi respuesta se basó en un predicado incorrecto y muy incorrecto. Para proporcionar uno correcto y no duplicar @vkp one, hice esta construcción monstruosa:
create table so74 as select * from (values (0, 1), (1, 1), (2, 1), (3, 2), (4, 2), (5, 2), (6, 1), (7, 1)) t(id, u); with d as ( with c as ( with b as ( select * , case when lag(u) over (order by id) <> u or id = min(id) over() then id end min , case when lead(u) over (order by id) <> u or id=max(id) over () then id end max from so74 ) select u, min,max from b where coalesce(min,max) is not null ) select u,min,lead(max) over () max from c ) select * from d where coalesce(min,max) is not null ; u | min | max ---+-----+----- 1 | 0 | 2 2 | 3 | 5 1 | 6 | 7 (3 rows) Time: 0.456 ms