SQL文実行するのに、複雑な条件だと爺の脳みそが追いつきません。今回もMicdrosoft:Copilotに助けてもらいました。
忘れないよう「備忘録」にしました。そもそも、よくわかってないままにできてしまった、というのが本当かもしれません。
- 株データが対象のSQL:変数とリストを使ってクエリ回数1回で実現できないものか…。
- 日付は期間、単CDだと考えやすいんだけど。
- 複合条件だとIN()の出番だけど….。
- Copilotに相談:あれこれ改善しながら、やっと成功~。
- 「+」使ってsqlパラメータ…。
株データが対象のSQL:変数とリストを使ってクエリ回数1回で実現できないものか…。
次のような条件でMySQLからデータを取得したいと妄想しました。
- 日付を期間で指定したい。変数で渡したい。
- 別行程で選んだ銘柄コード(cd、複数)がリストになっている。
- リストを一気にsql文で渡せたら、ひょっとして一回のSQLで取得できないか…。
これまでだと、(1)期間中の全データをMySQLから一気に取り込み、その後Pythonで対象cdのみ抽出する、(2)cdリストをfor文で回し、単cdの期間内データをMySQLから取得し、繰り返す、などの方法でやってました。
日付は期間、単CDだと考えやすいんだけど。
このままでは動きませんけど、ひとまずサンプルです。
# このスクリプトだけでは動きません #(略) con = pmsql.connect(**DB) dates=["2025-03-11","2025-03-13"] cdx = ['9201'] with con.cursor() as cur: sql = """ SELECT date, cd, volume FROM `market` WHERE date BETWEEN %s AND %s AND cd = %s """ params = [dates[0], dates[1], cdx] cur.execute(sql, params) results = cur.fetchall() print(results)
11日から13日の期間で銘柄コード9201を抽出し、日付と銘柄コード+αを取得する内容です。
爺が妄想したのは、「WHERE内のcdに変数を渡せるなら、ひょっとしてリスト(配列)を渡すこともできるのでは」ということでした。もし実現出来たら、何回もSQLしなくて済みそうです。
複合条件だとIN()の出番だけど….。
条件が、次のようになると、とたんに困ります。
dates=["2025-03-11","2025-03-13"]
cdx = ['9201', '9204']
すぐに思いつくのが「IN」を使うことですが、「cd=%s」のところを「cd IN (%s)」にしても期待する結果にならず、エラーでした。
Copilotに相談:あれこれ改善しながら、やっと成功~。
ラチがあかない爺の見通し~。ということでCopilotに相談しました。
JOINを使った書き方を教えてくれました。
すぐは成功せず、何回かエラー、リトライを繰り返し、次のような書き方で動きました。なお、部分なので、これだけでは動きません。
# 部分です。これだけでは動きません。 sql = """ SELECT date, cd, volume FROM `market` WHERE date BETWEEN %s AND %s AND cd IN (%s) ; """ % ( '%s', '%s', ', '.join(['%s'] * len(cdx)) ) params = [dates[0], dates[1], cdx]
「%s]がいっぱいあって、爺の脳みそでは十分に理解できません。
%sの対応関係は…。
WHERE date BETWEEN %s AND %s AND cd IN (%s)
(-----------------------------%s',-----'%s', --', '.join(['%s'] * len(cdx))
と上下に並べると、なんとなく関係が見えて来ました。
日付のBETWEENで使う変数は、JOINの前方にある二つの「%s」だと思います。そのあとの「%s」は銘柄コードを収めたリスト(cdx)の個数分を「,」を挟みながら用意し、全体としては「日付のふたつ、リストにあるcd数の合計分を変数として用意する」というようなことになるのだろう、と爺は想像しました。
「+」使ってsqlパラメータ…。
Copilotが教えてくれたsqlパラメータの書き方は次のようでした。
「params = [dates[0], dates[1]] + cdx」
「+」を使っても書けるようです。動かしてみたら、キッチリ動いてくれました。
初見でした。Python実装ではいろんな書き方が実現できるんですね~。単純なsqlくらいで使っていた、というのがこの間のCopilotの援助で、随分複雑なsql文を動かすことができるように…。ま、爺の短期記憶は霧散しそうなので、この際「備忘録」にしておこうということでした。