PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment écrire une fonction dans plpgsql qui compare une date avec un horodatage sans fuseau horaire ?

Ce que Pavel a dit.

De plus, rien n'indique un besoin de PL/pgSQL pour commencer. Un SELECT simple (préparé) déclaration peut le faire. Ou une fonction SQL, si vous souhaitez la conserver dans la base de données. Voir :

Et concernant :

Définir la limite supérieure / inférieure inclusive / exclusive précisément pour éviter des résultats de cas extrêmes surprenants. Lors de la comparaison d'un timestamp colonne à une date , ce dernier est contraint à l'horodatage signifiant la première instance de la journée :YYYY.MM.DD 00:00:00 .

Votre requête indique :

measurement_timestamp <= lastDate AND measurement_timestamp >= firstDate

... qui inclurait tout firstDate , mais exclure tout lastDate sauf pour la première instance (commune) à 00:00 . Généralement pas ce que vous voulez. Compte tenu de votre formulation, je suppose que c'est ce que vous voulez vraiment :

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

① Cela inclut tous les lastDate , et efficacement. Vous pouvez simplement ajouter/soustraire un entier integer valeur vers / depuis une date ajouter / soustraire des jours . Le cast explicite en ::timestamp est facultatif car la date serait automatiquement forcée dans l'expression. Mais puisque nous essayons de dissiper la confusion ici ...

Connexe :

A part 1 :

timestamp les valeurs ne sont pas formaté, point. Ce ne sont que des valeurs d'horodatage (stockées en interne sous forme de nombre de microsecondes depuis l'époque). L'affichage est complètement séparé de la valeur et peut être ajusté de cent et une manières sans changer la valeur . Débarrassez-vous de cette idée fausse pour mieux comprendre ce qui se passe. Voir :

A part 2 :

À propos de la nature sournoise de SQL BETWEEN :

A part 3 :

Considérez les identifiants légaux en minuscules dans Postgres. first_date au lieu de firstDate . Voir :

Connexe :