pagetakaBlog

最近リフォームと鳥取県日南町の記事多め。写真、PC、ネット等の話題も

MySQL:期間はBETWEENで変数、他項目複数のリストを渡しINとJOINで一気に取得。

SQL文実行するのに、複雑な条件だと爺の脳みそが追いつきません。今回もMicdrosoft:Copilotに助けてもらいました。
忘れないよう「備忘録」にしました。そもそも、よくわかってないままにできてしまった、というのが本当かもしれません。

株データが対象の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文を動かすことができるように…。ま、爺の短期記憶は霧散しそうなので、この際「備忘録」にしておこうということでした。