sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo escribo una función en plpgsql que compara una fecha con una marca de tiempo sin zona horaria?

Lo que dijo Pavel.

Además, nada indica la necesidad de PL/pgSQL para empezar. Un simple (preparado) SELECT declaración puede hacerlo. O una función SQL, si desea conservarla en la base de datos. Ver:

Y sobre:

Definir límite superior / inferior inclusivo / exclusivo precisamente para evitar resultados sorprendentes en casos de esquina. Al comparar una timestamp columna a una date , este último está obligado a la marca de tiempo que significa la primera instancia del día:YYYY.MM.DD 00:00:00 .

Tu consulta dice:

measurement_timestamp <= lastDate AND measurement_timestamp >= firstDate

... que incluiría todo firstDate , pero excluye todo lastDate excepto por la primera instancia (común) a las 00:00 . Normalmente no es lo que quieres. Dada su formulación, supongo que esto es lo que realmente quiere:

CREATE OR REPLACE FUNCTION get_measurements_by_node_and_date(node_id integer
                                                           , firstDate date
                                                           , lastDate date) 
  RETURNS TABLE (measurement_id integer
               , node_id integer
               , carbon_dioxide float8
               , hydrocarbons float8
               , temperature float8
               , humidity float8
               , air_pressure float8
               , measurement_timestamp timestamp)
  LANGUAGE sql STABLE AS
$func$
   SELECT m.id
        , m.node_id
        , m.carbon_dioxide
        , m.hydrocarbons
        , m.temperature
        , m.humidity
        , m.air_pressure
        , m.measurement_timestamp -- AS measure  -- just documentation
   FROM   public.measurements_lora m
   WHERE  m.node_id = _node_id
   AND    m.measurement_timestamp >= firstDate::timestamp
   AND    m.measurement_timestamp < (lastDate + 1)::timestamp  -- ①!
$func$;

① Esto incluye todo lastDate , y eficientemente. Simplemente puede sumar/restar un integer valor a/desde una date para sumar/restar días . La conversión explícita a ::timestamp es opcional ya que la fecha se coaccionaría en la expresión automáticamente. Pero como estamos tratando de aclarar la confusión aquí...

Relacionado:

Aparte 1:

No. timestamp los valores son no formateado, punto. Son solo valores de marca de tiempo (almacenados internamente como el número de microsegundos desde la época). La pantalla está completamente separada del valor y se puede ajustar de ciento una maneras sin cambiar el valor . Deshazte de este concepto erróneo para entender mejor lo que está pasando. Ver:

Aparte 2:

Acerca de la naturaleza tortuosa de SQL BETWEEN :

Aparte 3:

Considere los identificadores legales en minúsculas en Postgres. first_date en lugar de firstDate . Ver:

Relacionado: