#python #sql #pandas
#python #sql #pandas
Вопрос:
Я получаю некоторые данные из базы данных, используя операции запроса pandas read sql:
import pandas as pd
date_filter = '2020-01-01'
df = pd.read_sql_query(f"SELECT * FROM table WHERE date_id>= {date_filter }", my_connection)
Если я запущу этот код, фильтр не будет применен, и он выведет все данные.
Однако, если я заключу переменную в двойные кавычки:
df = pd.read_sql_query(f"SELECT * FROM table WHERE date_id>= '{date_filter }'", my_connection)
Это делает фильтр правильно.
Почему? Я допускаю какую-либо ошибку?
Комментарии:
1. Это имеет смысл, потому что в SQL вы бы фильтровали
'2020-01-01'
.2. Нет, вы не совершаете ошибку, SQL не любит необработанные строки даты без кавычек, потому что нет простого разделителя, чтобы распознать, что это один токен
Ответ №1:
Вам нужно обернуть апострофы вокруг переменной, потому что без переменной вы получите запрос типа
SELECT * FROM table WHERE date_id>= 2020-09-08
это недопустимый SQL. Вам нужно обернуть апострофами значение, чтобы иметь допустимый синтаксис:
SELECT * FROM table WHERE date_id>= '2020-09-08'
Именно по этой причине вам нужно обернуть апострофы вокруг вашего шаблона.
Ответ №2:
Без кавычек, я бы предположил, что анализатор SQL может выполнять вычитание частей года / месяца / дня в вашей переменной:
SELECT * FROM table WHERE date_id >= 2020-01-01
SELECT * FROM table WHERE date_id >= 2018
И поскольку большинство дат в базах данных отформатированы в секундах от эпохи ( 1970-01-01 00:00:00
). Удобочитаемое преобразование 2018
занимает несколько минут от epoch, в частности Thursday, January 1, 1970 12:33:38 AM
. Следовательно, почему возвращаются почти все ваши данные.
SELECT * FROM table WHERE date_id >= '1970-01-01 12:33:38'
Как вы узнали, цитирование буквальных значений даты работает, но еще лучшим решением является параметризация, которая поддерживается в pandas.read_sql
. Для ясности, F-строки — это не параметризация, а просто более новая версия интерполяции строк. Также обратите внимание, что заполнитель параметра отличается в зависимости от DB-API, и символ не должен заключаться в кавычки или объединяться в каких-либо арифметических или других операциях.
# cxOracle
df = pd.read_sql_query("SELECT * FROM table WHERE date_id >= :1",
my_connection, params=[date_filter])
# psycopg2, pymysql, pymssql
df = pd.read_sql_query("SELECT * FROM table WHERE date_id >= %s",
my_connection, params=[date_filter])
# pyodbc, sqlite3, ibm_db, jaydebeapi
df = pd.read_sql_query("SELECT * FROM table WHERE date_id >= ?",
my_connection, params=[date_filter])