本日は、RDB(リレーショナルデータベース)のことです。対象としたデータは株価です。
Microsoft:Copilotに教えてもらいました。少し簡略化してソースも載せます。
株価データを収めたテーブルの様子
テーブル「market」の一行の項目は次のようなものです。
- id:データ逐次番号
- date:市場日付
- cd:銘柄コード
- o:寄値
- h:高値
- l:安値
- c:引値
実際には他の項目もありますが、説明のため簡略化しました。
[当日寄値]-[前日引値]をSQLでどう書いたら?
同じテーブルで同一CDの、異なる市場日の項目の差分を、SQLだけで求める方法を知りませんでした。
これまでは、一回のSQLでデータ取得し、Python:Pandas:DataFrameで一方の項目をshiftしたのち計算というような計算をやってました。
実は、副問い合わせ(サブ・クエリ)も数日前まで使ったことなかったです。使ってみたら便利なのを実感しました。20年くらい前、職業訓練所で「外部結合」「内部結合」とか習った記憶はあります。しかし、テーブルは一つだし…と思いつつ、最後の切り札Microsoft:Copilotに尋ねました。
「自己結合で」とのことでした。早速、持っている本を開いてみました。初心者用の本には載ってませんでした。皮肉なことに、20年前に買った厚い本には「交差結合」を含め「自己結合」も載ってました…。
勉強が足りないというのは、こういうことですね。
ひとつのテーブルでも別名(エイリアス)を使い、あたかもふたつあるようにする…らしい。
「自己結合」のポイントは、「FROM market a JOIN market b」のところのようです。ひとつのテーブルがあたかもふたつのテーブル「a」「b」として操作できることになりました。
同じ銘柄コードの[当日寄値]と[前日引値]が一回で取得できるということは、(1)JOIN:結合する当日CD(a.cd)、前日CD(b.cd)の条件を満たした上で、(2)WHERE:日付をa.date、b.dateに具体的に代入し、(3)SELECT:必要なデータを取得する、という流れが実現できるようです。
aテーブルには当市場日、bテーブルには前市場日を指定すれば、a.oで当市場日寄値、b.cで前市場日引値を取得でき、差分計算ができる準備ができました。
サンプル・コード
サンプルコードだけでは動きません。MySQLなどRDBが稼働している事、SQLで操作できることが必要です。
#以下はコメントです。
※ 3/9 スクリプト訂正:
正:SELECT a.cd AS "cd", a.o - b.c AS "dif"
誤:SELECT a.cd AS "cd", a.o - b.ac AS "dif"
SELECT a.cd AS "cd", a.o - b.c AS "dif", a.o, b.c # CD、差分(a.o - b.c)、検算用に、当市場日寄値(a.o)、前市場日引値(b.c)を表示 FROM `market` a #テーブルmarketを別名 a として扱う JOIN `market` b ON a.cd = b.cd #テーブルmarketを別名 b として扱い、aとbの結合条件は同一cdであること WHERE a.cd = 1332 AND a.date = "2025-03-06" AND b.date = "2025-03-05" # データを探す日付は、a、b別日を指定する
なお、銘柄コードや日付などは、プレースホルダー、プリペアドステートメントなどを使えば変数として処理できる…と思います。また、他の項目同士の差分もSELECT文で書き分けることができそうです。
爺は、これでずいぶん楽になった気がします。
錯誤などありましたら、ご教示のほど。優し目に教えてください。今回も、Microsfot:Copilotに助けてもらいました。
3/9スクリプト補足:マッチするすべての銘柄コードを選択する場合
上記スクリプト「WHERE a.cd = 1332 AND」のうち「 a.cd = 1332 AND」を削除すると、マッチするCDすべてで、指定日間の差分計算ができます。