Función LAG dinámica (SQL estándar, BigQuery). ¿Es posible?

CorePress2024-01-24  8

Estoy intentando encontrar una solución para eso. También adjunto una imagen con una descripción general de lo que quiero, pero también escribiré aquí.

En la función LAG, ¿es posible tener un número dinámico en la sintaxis?

LAG(sessions, 3)

En lugar de usar 3, necesito el número de minutos de elevación de columna, que es 3 en este ejemplo, pero será diferente para cada situación.

He intentado usar LAG(sessions, minutosdelift) pero no es posible. Probé LAG(sessions, COUNT(minutosdelift)) y tampoco es posible.

El objetivo final es calcular la diferencia entre 52 y 6. Entonces, (52/6)-1, lo que me da 767%. Pero para hacerlo necesito un número dinámico en la función LAG (u otra idea para hacerlo).

He intentado usar FILAS ANTERIORES Y FILAS ANTERIORES SIN LÍMITES, peroDe nuevo se necesita un número literal.

Por favor, ¿alguna idea sobre cómo hacerlo? ¡Gracias!

Esta captura de pantalla podría explicarlo:

ingrese la descripción de la imagen aquí

Mi código: esta es la última consulta que he probado, porque tengo 7 vistas anteriores

SELECT 
    DATE, HOUR, MINUTE, SESSIONS, PROGRAMA_2, 
    janela_lift_teste, soma_sessao_programa_2, minutosdelift,
    CASE 
       WHEN minutosdelift != 0 
          THEN LAG(sessions, 3) OVER(ORDER BY DATE, HOUR, MINUTE ASC)
    END AS lagtest,
    CASE 
       WHEN programa_2 = "#N/A" OR programa_2 is null 
          THEN LAST_VALUE(sessions) OVER (PARTITION BY programa_2 ORDER BY DATE, HOUR, MINUTE ASC)
    END AS firstvaluetest,
FROM 
    tbl8
GROUP BY 
    DATE, HOUR, MINUTE, SESSIONS, PROGRAMA_2, 
    janela_lift_teste, minutosdelift, soma_sessao_programa_2
ORDER BY 
    DATE, HOUR, MINUTE ASC


------------------------------------

En BigQuery (como en otras bases de datos), el argumento de lag() tiene que ser una constante.

Un método para solucionar este problema utiliza una autounión. Me cuesta seguir tu consulta, pero la idea es:

with tt as (
      select row_number() over (order by sessions) as seqnum,
             t.*
      from t
     )
select t.*, tprev.*
from t join
     t tprev
     on tprev.seqnum = t.seqnum - minutosdelift;

4

¡Hola, Gordon! Gracias por responder mi pregunta aquí. Perdón por el retraso, pero como le dije a Mikhail estaba de vacaciones y estoy trabajando en ello ahora.

- julio.86

12 de mayo de 2021 a las 20:40

¡Hola, Gordon! Gracias por responder mi pregunta aquí. Perdón por el retraso, pero como le dije a Mikhail estaba de vacaciones y estoy trabajando en ello ahora. Intenté usar ROW_NUMBER() hasta ahora, pero realmente no puedo obtener el número correcto. No estoy seguro de poder compartirlo aquí.pero lo intentaré. ¡Estoy probando algunas soluciones y volveré para compartirlas contigo! Gracias

- julio.86

12 de mayo de 2021 a las 21:11

@julius.86. . . No entiendo tu comentario. Esto debería implementar la lógica que pide su pregunta.

- Gordon Linoff

13 de mayo de 2021 a las 2:33

¡Hola, Gordon! Sí, lo intenté hoy y funcionó. ¡Gracias por eso!Lo que intenté decir en el último comentario fue que intenté usar ROW_NUMBER() antes de mi pregunta aquí y no funcionó. Después de tu comentario funcionó. ¡Gracias!

- julio.86

13 de mayo de 2021 a las 22:08



------------------------------------

Considere el siguiente ejemplo: espero que pueda aplicar este enfoque a su caso de uso

#standardSQL
with `project.dataset.table` as (
  select 1 session, timestamp '2021-01-01 00:01:00' ts, 10 minutosdelift  union all
  select 2, '2021-01-01 00:02:00', 1 union all
  select 3, '2021-01-01 00:03:00', 2 union all
  select 4, '2021-01-01 00:04:00', 3 union all
  select 5, '2021-01-01 00:05:00', 4 union all
  select 6, '2021-01-01 00:06:00', 5 union all
  select 7, '2021-01-01 00:07:00', 3 union all
  select 8, '2021-01-01 00:08:00', 1 union all
  select 9, '2021-01-01 00:09:00', 2 union all
  select 10, '2021-01-01 00:10:00', 8 union all
  select 11, '2021-01-01 00:11:00', 6 union all
  select 12, '2021-01-01 00:12:00', 4 union all
  select 13, '2021-01-01 00:13:00', 2 union all
  select 14, '2021-01-01 00:14:00', 1 union all
  select 15, '2021-01-01 00:15:00', 11 union all
  select 16, '2021-01-01 00:16:00', 1 union all
  select 17, '2021-01-01 00:17:00', 8 
)
select a.*, b.session as lagtest
from `project.dataset.table` a 
left join `project.dataset.table` b
on b.ts = timestamp_sub(a.ts, interval a.minutosdelift minute)  

con salida

3

¡Hola, Mijaíl! Gracias por turespuesta. Estoy en mis vacaciones ahora. Tan pronto como regrese, sin duda lo intentaré y volveré aquí.

- julio.86

15 de abril de 2021 a las 4:02

¡Hola, Mijaíl! ¡Yo otra vez aquí! ¡Estoy trabajando en ello ahora y parece que tu solución podría funcionar bien! Gracias por compartir su conocimiento. Mi única preocupación es que mi conjunto de datos no está completo por fecha, hora y minuto. Entonces, el guión no tiene minutos antes, porque no hay estos minutos. Pero haré una prueba con un conjunto de datos completo y creo que funcionará. ¡Volveré aquí para hacértelo saber! ¡Gracias de nuevo!

- julio.86

12 de mayo de 2021 a las 20:36

¡Hola, Mijaíl! Tal como dijiste, funcionó para calcular datos antes. ¡Gracias de nuevo por responderme!

- julio.86

20 de mayo de 2021 a las 19:14

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare