Сообщить об ошибке.

Функция read_sql() модуля pandas в Python

Читает SQL-запрос или таблицу базы данных в DataFrame

Синтаксис:

import pandas

df = pandas.read_sql(sql, con, index_col=None, coerce_float=True, 
                     params=None, parse_dates=None, columns=None, 
                     chunksize=None, dtype_backend=no_default, dtype=None)

Параметры:

  • sql - SQL-запрос, который необходимо выполнить или имя таблицы.

  • con - строка соединения с базой данных в стиле SQLAlchemy или объект соединения (SQLAlchemy, sqlite3, DBAPI2 или ADBC). Использование SQLAlchemy позволяет использовать любую БД, поддерживаемую этой библиотекой. Объект DBAPI2 поддерживается только sqlite3.

    Пользователь несет ответственность за закрытие объекта соединения ADBC ​​и SQLAlchemy. Соединение, переданное как строка в стиле SQLAlchemy закрывается автоматически.

  • index_col=None - строка с именем столбца для установки в качестве индекса или список имен для MultiIndex.

  • coerce_float=True - пытается преобразовать значения таких объектов как например, decimal.Decimal в числа float.

  • params=None - список параметров, которые нужно передать в ожидаемый интерфейс форматирования SQL-запроса к базе данных. Синтаксис, используемый для передачи параметров, зависит от драйвера базы данных. Например, модуль psycopg2 использует форматирование %(name)s, следовательно необходимо использовать params={’name’ : ‘value’}.

    Напомним стили форматирования из PEP249:

    • qmark: ...WHERE name=?;
    • numeric: ...WHERE name=:1;
    • named: ...WHERE name=:name;
    • format: ...WHERE name=%s;
    • pyformat: ...WHERE name=%(name)s.

  • parse_dates=None - принимает:

    • список имен столбцов с датой/временем для анализа.
    • словарь вида {column_name: format}, где format совместима с правилами форматирования strftime в случае анализа времени строки или является одним из ('D', 's', 'ns', 'ms', 'us') в случае анализа целочисленных временных меток.
    • словарь вида {column_name: kwargs}, где kwargs соответствует ключевым аргументам функции pandas.to_datetime(). Особенно полезно для баз данных без встроенной поддержки datetime, таких как SQLite3.

  • columns=None - список имен столбцов для выбора из таблицы SQL (используется только при чтении таблицы).

  • chunksize=None - если указано, то возвращает итератор, где chunksize - количество строк, включаемых в каждый фрагмент.

  • dtype_backend=no_default - (экспериментальный) внутренний тип данных, применяемый к результирующему DataFrame.

    Поведение выглядит следующим образом:

    • 'numpy_nullable': возвращает фрейм с поддержкой null-dtype (по умолчанию).
    • 'pyarrow': возвращает фрейм данных ArrowDtype с нулевым значением, поддерживаемый pyarrow.

  • dtype=None - желаемый тип данных для столбцов результирующего DataFrame. Например, np.float64 (пытается применить ко всем столбцам) или словарь {’a’: np.float64, ‘b’: np.int32, ‘c’: ‘Int64’}, где ключ является именем столбца. Аргумент игнорируется, если вместо запроса передается таблица.

Возвращаемое значение:

Описание pandas.read_sql():

Функция read_sql() модуля pandas считывает SQL-запрос или таблицу базы данных в DataFrame.

Функция pandas.read_sql() является удобной оберткой двух функций pandas.read_sql_table() и pandas.read_sql_query() (для обратной совместимости). Она будет делегировать конкретную функцию в зависимости от предоставленных входных данных. SQL-запрос будет направлен в pandas.read_sql_query(), а имя таблицы базы данных - в pandas.read_sql_table(). Обратите внимание, что делегированная функция может иметь более конкретную функциональность.

Подключение к SQL БД

Чтобы подключиться с помощью драйвера ADBC, необходимо установить adbc_driver_sqlite с помощью менеджера пакетов. После установки можно использовать интерфейс DBAPI, предоставляемый драйвером ADBC.

import adbc_driver_sqlite.dbapi as sqlite_dbapi

# Создаем соединение
with sqlite_dbapi.connect("sqlite:///:memory:") as conn:
     df = pd.read_sql("data", conn)

Чтобы подключиться к SQLAlchemy, используем функцию create_engine() для создания объекта механизма из URI базы данных. Нужно создать движок только один раз для каждой базы данных, к которой подключаемся.

from sqlalchemy import create_engine

# Создаем движок.
engine = create_engine("sqlite:///:memory:")

Если нужно управлять своими собственными подключениями, то можно передать одно из них. В приведенном ниже примере открывается соединение с базой данных с помощью контекстного менеджера Python, который автоматически закрывает соединение после завершения блока.

# создадим экспериментальную базу данных
>>> import datetime
>>> c = ["id", "Date", "Col_1", "Col_2", "Col_3"]
d = [
    (26, datetime.datetime(2010, 10, 18), "X", 27.5, True),
    (42, datetime.datetime(2010, 10, 19), "Y", -12.5, False),
    (63, datetime.datetime(2010, 10, 20), "Z", 5.73, True),
]
>>> import pandas as pd
>>> data = pd.DataFrame(d, columns=c)
>>> from sqlalchemy import create_engine
>>> engine = create_engine("sqlite:///database.db")  
with engine.connect() as conn, conn.begin():
    # если возникают ошибки, то обновите `SQLAlchemy` 
    # например, pip install -U SQLAlchemy 
    data.to_sql("data", con=conn)

# теперь прочитаем ее
with engine.connect() as conn, conn.begin():
    data = pd.read_sql("data", conn)

>>> data
#    index  id       Date Col_1  Col_2  Col_3
# 0      0  26 2010-10-18     X  27.50   True
# 1      1  42 2010-10-19     Y -12.50  False
# 2      2  63 2010-10-20     Z   5.73   True

Примеры подключений:

from sqlalchemy import create_engine

engine = create_engine("postgresql://scott:tiger@localhost:5432/mydatabase")

engine = create_engine("mysql+mysqldb://scott:tiger@localhost/foo")

engine = create_engine("oracle://scott:tiger@127.0.0.1:1521/sidname")

engine = create_engine("mssql+pyodbc://mydsn")

# sqlite://<nohostname>/<path>
# где <path> относительный:
engine = create_engine("sqlite:///foo.db")

# или абсолютный, начиная с косой черты:
engine = create_engine("sqlite:////absolute/path/to/foo.db")

Расширенные запросы SQLAlchemy

Можно использовать конструкции SQLAlchemy для описания запроса. Используем sqlalchemy.text() для указания параметров запроса нейтральным способом для серверной части.

import sqlalchemy as sa

pd.read_sql(
    sa.text("SELECT * FROM data where Col_1=:col1"), engine, params={"col1": "X"}
)

Если есть описание базы данных SQLAlchemy, то можно выразить запрос, используя выражения SQLAlchemy.

metadata = sa.MetaData()

data_table = sa.Table(
    "data",
    metadata,
    sa.Column("index", sa.Integer),
    sa.Column("Date", sa.DateTime),
    sa.Column("Col_1", sa.String),
    sa.Column("Col_2", sa.Float),
    sa.Column("Col_3", sa.Boolean),
)

pd.read_sql(sa.select(data_table).where(data_table.c.Col_3 is True), engine)

Можно комбинировать выражения SQLAlchemy с аргументами, передаваемыми в pandas.read_sql(), используя sqlalchemy.bindparam().

import datetime as dt

expr = sa.select(data_table).where(data_table.c.Date > sa.bindparam("date"))
pd.read_sql(expr, engine, params={"date": dt.datetime(2010, 10, 18)})

Примеры использования pandas.read_sql():

При использовании базы данных SQLite принимаются только ванильные запросы SQL, поэтому указание только имени таблицы SQL (без SQL-запроса) приведет к ошибке.

>>> import pandas as pd
>>> from sqlite3 import connect
>>> conn = connect(':memory:')
# создадим `DataFrame` 
>>> df = pd.DataFrame(data=[[0, '10/11/12'], [1, '12/11/10']], columns=['int_column', 'date_column'])
# запишем `DataFrame` в SQLite
>>> df.to_sql(name='test_data', con=conn)
# 2

Читаем:

>>> pd.read_sql('SELECT int_column, date_column FROM test_data', conn)
#    int_column date_column
# 0           0    10/11/12
# 1           1    12/11/10

или если данные хранились в БД PostgreSQL:

>>> pd.read_sql('test_data', 'postgres:///db_name')

Анализируем даты в столбцах с помощью аргумента parse_dates. Аргумент parse_dates вызывает функцию pandas.to_datetime() для предоставленных столбцов. Пользовательские значения аргументов для применения to_datetime() к столбцу указываются при помощи спецификации словаря:

>>> pd.read_sql('SELECT int_column, date_column FROM test_data', conn,
...             parse_dates={"date_column": {"format": "%d/%m/%y"}})
#    int_column date_column
# 0           0  2012-11-10
# 1           1  2010-11-12

С версии pandas 2.2 поддерживает чтение БД через драйверы ADBC

>>> from adbc_driver_postgresql import dbapi  
>>> with dbapi.connect('postgres:///db_name') as conn:  
...     pd.read_sql('SELECT int_column FROM test_data', conn)
#    int_column
# 0           0
# 1           1

pandas.read_sql_query(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, chunksize=None, dtype=None, dtype_backend=no_default):

Функция pandas.read_sql_query() читает SQL-запрос в DataFrame. Возвращает DataFrame, соответствующий набору результатов строки запроса.

Чтобы использовать один из столбцов в качестве индекса, необходимо указать аргумент index_col, в противном случае будет использоваться индекс по умолчанию RangeIndex.

Аргумент sql представляет собой строку SQL-запроса, который необходимо выполнить. Можно передать строку запроса в стиле SQLAlchemy.

Аргумент con представляет собой строку соединения с базой данных в стиле SQLAlchemy или объект соединения (SQLAlchemy или sqlite3). Использование SQLAlchemy позволяет использовать любую БД, поддерживаемую этой библиотекой. Пользователь несет ответственность за закрытие соединения для соединения ADBC ​​и возможности подключения SQLAlchemy. Соединение, переданное как строка в стиле SQLAlchemy закрывается автоматически.

Описание остальных аргументов совпадают с описанием аналогичных аргументов, принимаемых функцией pandas.read_sql()

Пример использования pandas.read_sql_query():

Любые значения даты и времени с информацией о часовом поясе, анализируемые с помощью аргумента parse_dates, будут преобразованы в формат UTC.

>>> import pandas as pd
>>> from sqlalchemy import create_engine  
# БД `database.db` была создана выше
>>> engine = create_engine("sqlite:///database.db")  
>>> with engine.connect() as conn, conn.begin():  
...     data = pd.read_sql_query("SELECT * FROM data", conn)

Конечно, можно указать и более "сложный" запрос.

>>> with engine.connect() as conn, conn.begin():  
...     data = pd.read_sql_query("SELECT id, Col_1, Col_2 FROM data WHERE id = 42;", conn)

Функция read_sql_query() поддерживает аргумент chunksize. Если указать, то будет возвращаться итератор по фрагментам результата запроса:

>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame(np.random.randn(20, 3), columns=list("abc"))
>>> df.to_sql(name="data_chunks", con=engine, index=False)
for chunk in pd.read_sql_query("SELECT * FROM data_chunks", engine, chunksize=5):
    print(chunk)
#           a         b         c
# 0 -0.395347 -0.822726 -0.363777
# 1  1.676124 -0.908102 -1.391346
# 2 -1.094269  0.278380  1.205899
# 3  1.503443  0.932171 -0.709459
# 4 -0.645944 -1.351389  0.132023
#           a         b         c
# 0  0.210427  0.192202  0.661949
# 1  1.690629 -1.046044  0.618697
# 2 -0.013863  1.314289  1.951611
# 3 -1.485026  0.304662  1.194757
# 4 -0.446717  0.528496 -0.657575
#           a         b         c
# 0 -0.876654  0.336252  0.172668
# 1  0.337684 -0.411202 -0.828394
# 2 -0.244413  1.094948  0.087183
# 3  1.125934 -1.480095  1.205944
# 4 -0.451849  0.452214 -2.208192
#           a         b         c
# 0 -2.061019  0.044184 -0.017118
# 1  1.248959 -0.675595 -1.908296
# 2 -0.125934  1.491974  0.648726
# 3  0.391214  0.438609  1.634248
# 4  1.208707 -1.535740  1.620399

pandas.read_sql_table(table_name, con, schema=None, index_col=None, coerce_float=True, parse_dates=None, columns=None, chunksize=None, dtype_backend=no_default):

Функция pandas.read_sql_table() учитывая имя таблицы (аргумент table_name) и возможность подключения SQLAlchemy (аргумент con), читает SQL-таблицe в DataFrame. Эта функция не поддерживает соединения DBAPI.

Аргумент table_name - это строка с именем таблицы в базе данных.

Аргумент con может быть строкой подключения к БД (URI) в стиле SQLAlchemy или объект подключения SQLAlchemy

Аргумент schema представляет собой строку с именем схемы SQL в базе данных для запроса (если это поддерживается БД). Если None, то использует схему по умолчанию.

Описание остальных аргументов совпадают с описанием аналогичных аргументов, принимаемых функцией pandas.read_sql()

Пример использования pandas.read_sql_table():

>>> from sqlalchemy import create_engine  
# БД `database.db` была создана выше
>>> engine = create_engine("sqlite:///database.db")  
>>> pd.read_sql_table("data", engine)
#    index  id       Date Col_1  Col_2  Col_3
# 0      0  26 2010-10-18     X  27.50   True
# 1      1  42 2010-10-19     Y -12.50  False
# 2      2  63 2010-10-20     Z   5.73   True

Имя столбца в качестве индекса DataFrame и указать подмножество столбцов для чтения.

>>> pd.read_sql_table("data", engine, index_col="id")
    index       Date Col_1  Col_2  Col_3
id                                      
26      0 2010-10-18     X  27.50   True
42      1 2010-10-19     Y -12.50  False
63      2 2010-10-20     Z   5.73   True

>>> pd.read_sql_table("data", engine, columns=["Col_1", "Col_2"])
  Col_1  Col_2
0     X  27.50
1     Y -12.50
2     Z   5.73

Заставим явно анализировать столбцы как даты:

>>> pd.read_sql_table("data", engine, parse_dates=["Date"])
   index  id       Date Col_1  Col_2  Col_3
0      0  26 2010-10-18     X  27.50   True
1      1  42 2010-10-19     Y -12.50  False
2      2  63 2010-10-20     Z   5.73   True

При необходимости можно явно указать строку формата или набор аргументов для передачи в pandas.to_datetime():

>>> pd.read_sql_table("data", engine, parse_dates={"Date": "%Y-%m-%d"})
   index  id       Date Col_1  Col_2  Col_3
0      0  26 2010-10-18     X  27.50   True
1      1  42 2010-10-19     Y -12.50  False
2      2  63 2010-10-20     Z   5.73   True

>>> pd.read_sql_table(
...     "data",
...     engine,
...     parse_dates={"Date": {"format": "%Y-%m-%d %H:%M:%S"}},
... )
   index  id       Date Col_1  Col_2  Col_3
0      0  26 2010-10-18     X  27.50   True
1      1  42 2010-10-19     Y -12.50  False
2      2  63 2010-10-20     Z   5.73   True