Python - фильтрация SQL-запросов по датам - PullRequest
0 голосов
/ 12 сентября 2018

Я пытаюсь создать запрос SQL, который будет фильтровать по системной дате (запрос всех продаж за последние 7 дней):

import datetime
import pandas as pd
import psycopg2

con = p.connect(db_details)
cur = con.cursor()

df = pd.read_sql("""select store_name,count(*) from sales 
     where created_at between datetime.datetime.now() - (datetime.today() - timedelta(7))""",con=con)

Я получаю ошибку

psycopg2.NotSupportedError: cross-database references are not implemented: datetime.datetime.now

Ответы [ 4 ]

0 голосов
/ 12 сентября 2018

На самом деле, вам не обязательно нужны какие-либо параметры или вычисления в Python.Просто используйте соответствующий оператор SQL, который должен выглядеть следующим образом:

select store_name,count(*)
from sales 
where created_at >= now()::date - 7
group by store_name

Редактировать: я также добавил group by, который, я думаю, отсутствует.

0 голосов
/ 12 сентября 2018

Возможно, вам следует удалить этот код Python внутри вашего SQL, вычислить даты в python и затем использовать функцию strftime для преобразования их в строки.

Тогда вы сможете использовать их в своем запросе SQL,

0 голосов
/ 12 сентября 2018

Вы смешиваете синтаксис Python в свой SQL-запрос.SQL анализируется и выполняется базой данных, а не Python, и база данных ничего не знает о datetime.datetime.now() или datetime.date() или timedelta()!Конкретная ошибка, которую вы видите, вызвана тем, что ваш код Python интерпретируется как SQL, а как SQL , datetime.datetime.now ссылается на столбец now таблицы datetime в базе данных datetime, котораяперекрестная ссылка на базу данных, и psycopg2 не поддерживает запросы, которые включают несколько баз данных.

Вместо этого используйте Параметры SQL для передачи значений из Python в базу данных.Используйте заполнители в SQL, чтобы показать драйверу базы данных, куда должны идти значения:

params = {
    # all rows after this timestamp, 7 days ago relative to 'now'
    'earliest': datetime.datetime.now() - datetime.timedelta(days=7),
    # if you must have a date *only* (no time component), use
    # 'earliest': datetime.date.today() - datetime.timedelta(days=7),
}
df = pd.read_sql("""
     select store_name,count(*) from sales 
     where created_at >= %(latest)s""", params=params, con=con)

Используются заполнители, как определено в psycopg2 документации параметров , где %(latest)s относится кключ latest в словаре params.datetime.datetime() экземпляры напрямую поддерживаются драйвером.

Обратите внимание, что я также исправил выражение 7 дней назад , и заменили синтаксис BETWEEN на >=;без второй даты вы не запрашиваете значения между двумя датами, поэтому используйте >=, чтобы ограничить столбец датами после или после указанной даты.

0 голосов
/ 12 сентября 2018

datetime.datetime.now() не является правильным синтаксисом SQL, и поэтому не может быть выполнен read_sql(). Я предлагаю либо использовать правильный синтаксис SQL, который вычисляет текущее время, либо создать переменные для каждого datetime.datetime.now() и datetime.today() - timedelta(7) и заменить их в вашей строке.

изменить: не следовать второму предложению. См. Комментарии Мартина Питерса ниже.

...