「プログラマのためのSQL第4版」のサンプルコードをMySQLで動くようにしてみた(38.5 その他の時間関数)
目次
本エントリの概要
- 「プログラマのためのSQL第4版」の読書会に参加させてもらってるのですが、たまには予習をしようと思い付きでやってみました。
- 突発的なやつなので継続はしないつもりです。
- 本エントリでは動かすことが目的なので内容の理解は後回しです。
第38章 38.5 その他の時間関数 P730
元のSQL
CREATE FUNCTION Zeller (z_year IN INTEGER, z_month IN INTEGER, z_day IN INTEGER) RETURN INTEGER IS m INTEGER; d INTEGER; y INTEGER; BEGIN y := z_year; m := z_month - 2; IF (m <= 0) THEN m := m + 12; y := y - 1; END IF; RETURN (MOD((z_day + (13 * m - 1)/5 + 5 * MOD(y, 100)/4 - 7 * y/400), 7) + 1); END;
CREATE FUNCTION Zeller (z_year INTEGER, z_month INTEGER, z_day INTEGER) RETURNS INTEGER DETERMINISTIC BEGIN DECLARE m INTEGER; DECLARE d INTEGER; DECLARE y INTEGER; SET y = z_year; SET m = z_month - 2; IF (m <= 0) THEN SET m = m + 12; SET y = y - 1; END IF; RETURN (MOD((z_day + (13 * m - 1)/5 + 5 * MOD(y, 100)/4 - 7 * y/400), 7) + 1); END;
ポイント
- 関数のパラメーター
z_year IN INTEGER
の部分をz_year INTEGER
のように書きなおします。 RETURN INTEGER
としているところをRETURNS INTEGER DETERMINISTIC
に書き換えます。- IS以降で記載している変数宣言をBEGIN以下に移動します。
- 変数宣言はそれぞれ
DECLARE
をつけてDECLARE m INTEGER;
のようにます。 - 変数への値の代入は
y := z_year;
からSET y = z_year;
のように書きなおします。
検証
次回の読書会の日付 2019/02/28(木) を調べてみます。
mysql> SELECT Zeller(28,2,2019); +-------------------+ | Zeller(28,2,2019) | +-------------------+ | 5 | +-------------------+ 1 row in set (0.02 sec)
「ツェラーの公式」なるものがあるらしいので検索してみると Wikipedia ツェラーの公式 に、2パターンの式があります。
このうち、木曜日が5になるのは h(ISO 8601ではない方)としている方だということになります。
一応Wikipediaに書いてある計算式で手計算してみたけどhの方で合ってました。
(公式にあるグレゴリオ暦とユリウス暦での分岐は上記関数にはなく、1582年以降を想定しているようです。)
結果
- 動きました。
検証環境
MySQL8.0.12
PostgreSQLのDOW
書籍本文には
PostgreSQLはDOWという入力の日付に対する曜日を返す関数を持っている。2~8の値を返し、8が日曜日である。
と書かれていますが、なんとなく違和感があったので畑違いですが調べてみました。(そもそも畑持ってないけど)
①EXTRACT または date_part関数
https://www.postgresql.jp/document/10/html/functions-datetime.html
SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
SELECT date_part('dow' FROM TIMESTAMP '2001-02-16 20:38:40');
が返すのは 日曜日(0)から土曜日(6)までの曜日
・・・これではないですね。
②to_char関数
https://www.postgresql.jp/document/10/html/functions-formatting.html
to_char(timestamp, 'D')
または to_char(timestamp, 'ID')
が返すのは 曜日番号、日曜日(1)から土曜日(7)まで
(IDはISO 8601のそれ)だそうなのでこれでもないですね。
(そもそもDOWではない)
なんなんでしょう?
(正誤表にはありませんでした)