Interroger les séries temporelles de QuestDb à l'aide de Pandas avec des paramètres

Jan 13 2021

J'essaie de charger les données de séries chronologiques de QuestDb vers Pandas Dataframe. J'essaye d'utiliser le pilote Postgres comme

import pandas as pd
from sqlalchemy import create_engine
from datetime import datetime

engine = create_engine('postgresql://admin:quest@localhost:8812/mydb')
df = pd.read_sql_query(
  "select * from cases where ts between %(dstart)s and %(dfinish)s",
  con=engine, 
  params={"dstart":datetime(2020,12,24,16,0),"dfinish":datetime(2021,1,1,0,0)})

Mais reviens

DatabaseError: (psycopg2.DatabaseError) between/and parameters must be constants
LINE 1: ...etry where ts between '2020-12-24T16:00:00'::timestamp ...

J'ai aussi essayé d'utiliser> et <au lieu de BETWEEN

df = pd.read_sql_query(
  "select * from cases where ts > %(dstart)s and ts < %(dfinish)s",
  con=engine, 
  params={"dstart":datetime(2014,6,24,16,0),"dfinish":datetime(2014,6,24,17,0)})

Mais toujours pas de chance

DatabaseError: (psycopg2.DatabaseError) unsupported class
LINE 1: ... > '2020-06-24T16:00:00'::timestamp and ts < '2021-01-0...

Cela fonctionne sans paramètres, donc ce n'est pas tout à fait faux, mais il me manque quelque chose ici.

Réponses

4 AlexdesPelagos Jan 13 2021 at 05:40

QuestDb prend en charge le pilote Postgres mais n'est pas entièrement compatible avec les requêtes SQL. Peu de bits ne fonctionnent pas, donc BETWEEN ne peut apparemment être utilisé qu'avec des constantes. De plus, lorsque vous utilisez des paramètres datetime python, ils sont convertis '2020-06-24T16:00:00'::timestampdans la requête, ce qui n'est pas non plus pris en charge par QuestDb

La solution de contournement consiste à transmettre des paramètres de chaîne et à les convertir en horodatage dans la requête elle-même, quelque chose comme

df = pd.read_sql_query(
  "select * from cases where ts > to_timestamp(%(dstart)s, 'yyyy-MM-dd HH:mm:ss') " + 
  "and ts < to_timestamp(%(dfinish)s, 'yyyy-MM-dd HH:mm:ss')",
  con=engine, 
  params={"dstart":datetime(2020,12,24,16,0).strftime("%Y-%m-%d %H:%M:%S"),
  "dfinish":datetime(2021,6,24,17,0).strftime("%Y-%m-%d %H:%M:%S")})

C'est la même chose que dans le Trenton mentionné dans les commentaires.