web-dev-qa-db-ja.com

Pandas read_sql_query in other paramsでパラメータにリストをバインドする

私は自分のコードを実行するためのさまざまな方法をテストしようとしています。まず、私はこのリストを持っています:

member_list = [111,222,333,444,555,...]

私はそれをこのクエリに渡そうとしました:

query = pd.read_sql_query(
"""
select member id
    ,yearmonth
from queried_table
where yearmonth between ? and ?
    and member_id in ?
""", db2conn, params = [201601, 201603, member_list])

ただし、次のエラーが表示されます。

'無効なパラメータタイプ。 param-index = 2 param-type = list '、' HY105 '

だから私は周りを見て、フォーマットされた文字列を使ってみました:

query = pd.read_sql_query(
"""
select member id
    ,yearmonth
from queried_table
where yearmonth between ? and ?
    and member_id in (%s)
""" % ','.join(['?']*len(member_list), db2conn, params = [201601, 201603, Tuple(member_list)])

今、私はエラーを受け取ります:

'SQLには18622個のパラメーターマーカーが含まれていますが、3つのパラメーターが指定されました'、 'HY000'

これは、フォーマットされた文字列内のすべての?プレースホルダーを埋めようとしているためです。

したがって、最終的には、リストを何らかの方法で評価して?にバインドする個々の要素を渡す方法はありますか、またはこれを機能させるために使用できる別の方法はありますか?

ところで、私はpyodbcをコネクタとして使用しています。

前もって感謝します!

8
Scratch'N'Purr

これを3つの部分に分割して、問題を特定して読みやすくします。

  1. SQL文字列を作成する
  2. パラメータ値を設定する
  3. 実行 pandas.read_sql_query

SQLを構築する

まず、?プレースホルダーが正しく設定されていることを確認します。 str.formatstr.join および len とともに使用して、?の長さに基づいてmember_listsを動的に入力します。以下の例では、3つのmember_list要素を想定しています。

member_list = (1,2,3)
sql = """select member_id, yearmonth
         from queried_table
         where yearmonth between {0} and {0}
         and member_id in ({1})"""
sql = sql.format('?', ','.join('?' * len(member_list)))
print(sql)

戻り値

select member_id, yearmonth
from queried_table
where yearmonth between ? and ?
and member_id in (?,?,?)

パラメータ値を設定する

ここで、パラメーター値がflatタプルに編成されていることを確認します

# generator to flatten values of irregular nested sequences,
# modified from answers http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python
def flatten(l):
    for el in l:
        try:
            yield from flatten(el)
        except TypeError:
            yield el

params = Tuple(flatten((201601, 201603, member_list)))
print(params)

戻り値

(201601, 201603, 1, 2, 3)

Execute

最後に、sql値とparams値をread_sql_query呼び出しでまとめます。

query = pd.read_sql_query(sql, db2conn, params)
6
Bryan

python 3.6+を使用している場合は、クエリにフォーマットされた文字列リテラルを使用することもできます(cf https://docs.python.org/3/whatsnew/3.6。 html#whatsnew36-pep 498

start, end = 201601, 201603
selected_members = (111, 222, 333, 444, 555)  # requires to be a Tuple

query = f"""
    SELECT member_id, yearmonth FROM queried_table
    WHERE yearmonth BETWEEN {start} AND {end}
      AND member_id IN {selected_members}
"""

df = pd.read_sql_query(query, db2conn)
0
Bluu