Я пытаюсь использовать функцию pandas read_sql для запроса некоторых данных из базы данных sqlite. Мне нужно использовать параметризованный SQL, который содержится в предложении (List) и некоторых статических параметрах.
Ниже мой запрос
battingDataQuery = ('SELECT ID, MATCH_DATE, ROLE, DOWN_NUM, NAME, RUNS,'
'MATCH_ID, TEAM_NAME, VERSUS_TEAM_NAME, GROUND_NAME '
'FROM BATTING_DATA WHERE ID in ({1}) '
'AND DOWN_NUM < {0} AND MATCH_TYPE = {0}')
Я правильно добавил заполнители, используя формат
battingDataQuery = battingDataQuery.format('?', ','.join('?' * len(playerIdList)))
Мой сгенерированный SQL выглядит следующим образом
'SELECT ID FROM BATTING_DATA WHERE ID in (?,?,?,?,?) AND DOWN_NUM < ? AND MATCH_TYPE = ?'
Я застрял в последней части, где я отправляю параметры следующим образом:
battingDataDF = pd.read_sql_query(battingDataQuery , conn, params=(playerIdList,battingDownNum,'\'T20\''))
Я получаю следующую ошибку при использовании этого
Поставлено неправильное количество креплений. Текущий оператор использует 7, и есть 3 поставленных.
Я пытался использовать следующие варианты, но все равно получаю ту же ошибку
battingDataDF = pd.read_sql_query(battingDataQuery , conn, params=[playerIdList,battingDownNum,'\'T20\'']) # same error
battingDataDF = pd.read_sql_query(battingDataQuery , conn, params=[playerIdList,battingDownNum,'\'T20\'']) # same error
battingDataDF = pd.read_sql_query(battingDataQuery , conn, params=[tuple(playerIdList),battingDownNum,'\'T20\'']) # same error
Вы должны предоставить список из 7 параметров для ваших 7 вопросительных знаков:
battingDataDF = pd.read_sql_query(battingDataQuery , conn, params=playerIdList + [battingDownNum, "'T20'"])
(вы указали 3 параметра: список из 5 чисел, число и строку, отсюда и ошибка)
спасибо, это сработало. Хотя я смог найти другой вариант, который работал
Ответ, учитывая, что мой @stef сработал, но я смог найти другой вариант, который сработал. Так хотел опубликовать это ради завершения
battingDataDF = pd.read_sql_query(battingDataQuery , conn, params=(*playerIdList,battingDownNum,matchType))
*вызывает распаковку списка, что приводит к предоставлению правильного количества аргументов
Не уверен, какой подход лучше. Если кто-то может пролить свет на это, это будет здорово.
Я думаю, это просто вопрос вкуса: playerIdList + [battingDownNum, "'T20'"]
преобразует два последних аргумента в список, а затем объединяет два списка, тогда как (*playerIdList, battingDownNum, "'T20'")
сначала распаковывает список, а затем преобразует все аргументы обратно в кортеж. Таким образом, в обоих случаях мы получаем список или кортеж всех аргументов, которые в конечном итоге превращаются в список и объединяются с оператором запроса.
Поэтому я бы предпочел предыдущее решение, поскольку распаковка списка только для повторной упаковки его в другой список кажется мне менее интуитивно понятной, но, как я уже сказал, это вопрос личных предпочтений.
@Neel: извините за несколько правок/удалений, теперь все правильно и проверено.