Consultar series temporales de QuestDb usando Pandas con parámetros

Jan 13 2021

Estoy tratando de cargar datos de series temporales de QuestDb a Pandas Dataframe. Estoy tratando de usar el controlador de Postgres como

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)})

Pero regresé

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

También intenté usar> y <en lugar 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)})

Pero aun sin suerte

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

Funciona sin parámetros, por lo que no está del todo mal, pero me falta algo aquí.

Respuestas

4 AlexdesPelagos Jan 13 2021 at 05:40

QuestDb tiene soporte para controladores Postgres pero no es totalmente compatible con consultas SQL. Pocos bits no funcionan, por lo que BETWEEN aparentemente solo se puede usar con constantes. Además, cuando usa parámetros de fecha y hora de Python, se convierten '2020-06-24T16:00:00'::timestampen la consulta, que tampoco es compatible con QuestDb

La solución alternativa es pasar parámetros de cadena y convertirlos en marcas de tiempo en la consulta, algo como

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")})

Eso es lo mismo que en el Trenton mencionado en los comentarios.