es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Tratando de determinar si un valor está por debajo de un cierto criterio durante una duración especificada dentro de una ventana de tiempo con datos de series temporales.

Estoy trabajando con datos de series temporales de Timescale y estoy obteniendo un resultado de

{"sensor_id"=>41, "ts"=>"2021-12-22 18:58:22.320738 +0000", "std_name"=>"CW", "plant_id"=>139, "value"=>41.0}
{"sensor_id"=>41, "ts"=>"2021-12-22 18:58:22.315896 +0000", "std_name"=>"CW", "plant_id"=>139, "value"=>41.0}
{"sensor_id"=>41, "ts"=>"2021-12-22 18:48:22.319072 +0000", "std_name"=>"CW", "plant_id"=>139, "value"=>40.0}
{"sensor_id"=>41, "ts"=>"2021-12-22 18:48:22.314071 +0000", "std_name"=>"CW", "plant_id"=>139, "value"=>40.0}
{"sensor_id"=>41, "ts"=>"2021-12-22 18:33:22.317477 +0000", "std_name"=>"CW", "plant_id"=>139, "value"=>39.0}
{"sensor_id"=>41, "ts"=>"2021-12-22 18:33:22.30453 +0000", "std_name"=>"CW", "plant_id"=>139, "value"=>39.0}

Estoy intentando crear una consulta SQL donde, en los últimos 89 minutos, haya algún período de 30 minutos en el que el valor sea menor a 40 o algún número arbitrario. Estoy trabajando en Rails y creo que puedo encontrar una solución en Rails, pero no creo que sea la más limpia.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para crear una consulta SQL para esto, puedes usar una función de ventana para particionar los datos en intervalos de 30 minutos y calcular el valor promedio para cada intervalo. Luego, puedes filtrar cualquier intervalo donde el valor promedio sea menor que el umbral deseado.

    Aquí tienes un ejemplo de consulta:

    SELECT DISTINCT ON (time_bucket('30 minutes', ts)) 
      time_bucket('30 minutes', ts) as interval_start,
      avg(value) as avg_val
    FROM timeseries_data
    WHERE ts >= NOW() - INTERVAL '89 minutes'
    GROUP BY time_bucket('30 minutes', ts)
    HAVING avg(value) < 40
    

    Esta consulta utiliza la función time_bucket para agrupar los datos en intervalos de 30 minutos. La cláusula DISTINCT ON asegura que solo regresemos la primera fila para cada intervalo, que tendrá el tiempo de inicio del intervalo y el valor promedio. La cláusula HAVING filtra los intervalos donde el valor promedio es menor que 40.

    En Rails, puedes ejecutar esta consulta utilizando el método find_by_sql de ActiveRecord:

    query = <<-SQL
      SELECT DISTINCT ON (time_bucket('30 minutes', ts)) 
        time_bucket('30 minutes', ts) as interval_start,
        avg(value) as avg_val
      FROM timeseries_data
      WHERE ts >= NOW() - INTERVAL '89 minutes'
      GROUP BY time_bucket('30 minutes', ts)
      HAVING avg(value) < 40
    SQL
    
    results = TimeseriesData.find_by_sql(query)
    

    Esto devolverá un arreglo de objetos ActiveRecord::Result, cada uno representando una fila de los resultados de la consulta. Puedes extraer el tiempo de inicio del intervalo y el valor promedio de esta manera:

    results.each do |row|
      interval_start = row["interval_start"]
      avg_val = row["avg_val"]
      # haz algo con los datos...
    end
    

Comments are closed.