PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come scrivo una funzione in plpgsql che confronta una data con un timestamp senza fuso orario?

Cosa ha detto Pavel.

Inoltre, nulla indica la necessità di PL/pgSQL per cominciare. Un semplice (preparato) SELECT dichiarazione può farlo. O una funzione SQL, se vuoi mantenerla nel database. Vedi:

E riguardo a:

Definire il limite superiore/inferiore inclusivo/esclusivo precisamente per evitare risultati sorprendenti in caso d'angolo. Quando si confronta un timestamp colonna a una date , quest'ultimo è costretto al timestamp che indica la prima istanza del giorno:YYYY.MM.DD 00:00:00 .

La tua domanda dice:

measurement_timestamp <= lastDate AND measurement_timestamp >= firstDate

... che includerebbe tutto firstDate , ma esclude tutto lastDate fatta eccezione per la prima istanza (comune) alle 00:00 . Di solito non è quello che vuoi. Data la tua formulazione, suppongo che questo sia quello che vuoi veramente:

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$;

① Questo include tutto lastDate , ed efficiente. Puoi semplicemente aggiungere/sottrarre un integer valore a/da una date per aggiungere/sottrarre giorni . Il cast esplicito a ::timestamp è facoltativo poiché la data verrebbe automaticamente forzata nell'espressione. Ma dal momento che stiamo cercando di chiarire la confusione qui ...

Correlati:

A parte 1:

No. timestamp i valori sono non formattato, punto. Sono solo valori di timestamp (memorizzati internamente come numero di microsecondi dall'epoca). La visualizzazione è completamente separata dal valore e può essere regolata in centouno modi senza modificare il valore . Sbarazzati di questo malinteso per capire meglio cosa sta succedendo. Vedi:

A parte 2:

Sulla natura subdola di SQL BETWEEN :

A parte 3:

Considera gli identificatori legali e minuscoli in Postgres. first_date invece di firstDate . Vedi:

Correlati: