Время прочтения: 4 мин.

Дата-аналитик редко сталкивается только с одним видом баз данных. Это может быть база Oracle, MS SQL, TERADATA, Облако данных и другие.

Иногда есть возможность импорта в базу данных, но, когда его нет, на помощь приходит Python совместно с оператором SQL IN. Особенно удобно его использовать в базе данных Oracle, но есть способ и для T-SQL.

Итак, представим себе задачу, которая может возникнуть, перед аналитиком. Предположим у нас есть список ФИО с датами рождения, который нужно «прогнать» по определённым таблицам в базе данных Oracle или MS. Песочницы в базе данных нет. Поэтому простым соединением по двум полям не обойтись.

            Импортируем необходимые библиотеки и загрузим наш список с ФИО и датой рождения в датафрейм Python.

import cx_Oracle
import pyodbc as sql_db_connect
import pandas as pd
data = pd. read_csv(“data.csv”)

Пусть в нем будет два поля ENAME и EBIRTH.

Для Oracle и MS SQL данная задача решается по-разному. Рассмотрим каждое решение отдельно.

Для Oracle

            Прежде всего нам необходимо подготовить строчку, которую будем вставлять в текст запроса с оператором IN. Синтаксис в Oracle для оператора IN c группировкой следующий:

            (D_1, D_2, D_3) in (( ‘a1’, ‘b1′ ,’c1’ ), ( ‘a2’, ‘b2′ ,’c2’ )), где в левой части названия колонок, а в  правой части сгруппированные условия.

            Следующим шагом необходимо преобразовать исходный датафрейм с ФИО и датой рождения в список строк, где каждая строка будет содержать 990 сгруппированных условий. Данное число обусловлено ограничением на количество условий внутри оператора IN.

Ниже приведён код, который позволит нам создать такой список

id_ename = [ ]  # Создаем пустой  список для ФИО
id_bd = [ ]        # Создаем пустой список для дат рождения

Циклом заполняем списки

for i in range(len(ids)):
id_ename.append(data ['ENAME'][i])
id_bd.append(data ['EBIRTH'][i])
union_list = [ ]
a= '(' + """ ' ' """ + ',' + """ ' ' """ + ')'  Первое условие, к которому присоединяем остальные
b = [ ]
for i in range(len(data)):
a = a + ',' + '(' + """ ' """ + str(ids_ename[i]) + """ ' """ + \
',' + """ ' """ + str(ids_bd[i]) + """ ' """ + ')'
b.append(i) 
if len(b) > 990:
b = []
union_list.append(a)
a= '(' + """ '' """ + ',' + """ ' ' """ + ')'
union_list.append(a)

После формирования списка запускаем цикл выполнения запроса по 990 шт.

conn = cx_Oracle.connect()
sql_query = r""" select * from A
where  (A.name , A.date_pers) in ({})
for i in union_list: 
df = pd.read_sql(sql_linenums.format(i), conn)

Для MS SQL

При работе в T-SQL данная задача решается чуть сложнее, так как указать несколько столбцов для оператора IN нельзя. Для начала необходимо сделать группировку по дате рождения, т.е. сгруппировать всех, кто родился в один день.

Для этого создадим список уникальных дат

Unic_data['дата'] = data ['Дата решения'].drop_duplicates()
Unic_data.reset_index(inplace = True, drop = True)

Создаем список списков где нулевым элементом будет ФИО до 990 штук, а первым элементом — дата рождения.

union_list = [ ]
for i in range(Unic_data): цикл по датам рождения
ids_list = []
ids_list = list(data.loc[(data['EBIRTH '] == Unic_data ['дата'][i])][' ENAME ']) 
a = """ ' ' """
b = []
for j in range(len(ids_list)):
a=a + ', ' + str(ids_list[j])
b.append(j)
if len(b) > 990:
b = [ ]
union_list.append([a, Unic_data ['дата'][i]])
a  =  """ ' ' """
           union_list.append([a, Unic_data ['дата'][i]])

После формирования списка запускаем цикл выполнения запроса по 990 шт.

conn = sql_db_connect.connect(server))
sql_query = r""" select * from A
where  A.name in ({})
and A. date_pers = {}
for i in union_list: 
df = pd.read_sql(sql_query.format(i[0] , i[1]) , conn)

Таким образом, используя выше изложенные алгоритмы, мы можем, не импортируя файлы на сервер, получать информацию из баз данных. Это очень важно, так как возможность импорта есть не всегда. При этом не ограничивать себя лишь одним критерием. Критериями могут быть не только ФИО и дата рождения, а любые другие, которые надо учитывать одновременно.