最後の以外は業務でも役に立つことがあるかも知れませんが、最後のは完全に趣味の世界です。
もしかしたら今後役に立つことがあるかも知れないので記録しておきます。
やること
- 日付の所属週の月曜日を求める
- 日付の所属月の月初日を求める
- 日付の所属月の末日を求める
- 日付の所属月の日付を全て表示する
- 日付の所属月のカレンダーを表示する(曜日がカラム)
前提条件
- MariaDB 10.2以降(11.4.5を使っていきます)
日付の所属週の月曜日を求める
対象日付を「2025/08/17(日)~2025/08/25(月)」として
次の計算ルールを適用してみます。
▼計算ルール:
- 週の始まりを月曜とする
- 日付の所属週の月曜を求める
▼対応方針
WEEKDAY()関数が返す数値(月曜が0、日曜が6)を使って、
DATE_SUB()関数で対象日付から曜日分を引き算すればOK。
▼SQL
SELECT
target_date,
CASE
WHEN WEEKDAY(target_date) = 0 THEN '月'
WHEN WEEKDAY(target_date) = 1 THEN '火'
WHEN WEEKDAY(target_date) = 2 THEN '水'
WHEN WEEKDAY(target_date) = 3 THEN '木'
WHEN WEEKDAY(target_date) = 4 THEN '金'
WHEN WEEKDAY(target_date) = 5 THEN '土'
WHEN WEEKDAY(target_date) = 6 THEN '日'
END AS 'youbi',
DATE_FORMAT(DATE_SUB(d.target_date, INTERVAL WEEKDAY(d.target_date) DAY), '%Y/%m/%d') AS `monday`
FROM
(
SELECT '2025/08/17' AS `target_date`
UNION ALL SELECT '2025/08/18' AS `target_date`
UNION ALL SELECT '2025/08/19' AS `target_date`
UNION ALL SELECT '2025/08/20' AS `target_date`
UNION ALL SELECT '2025/08/21' AS `target_date`
UNION ALL SELECT '2025/08/22' AS `target_date`
UNION ALL SELECT '2025/08/23' AS `target_date`
UNION ALL SELECT '2025/08/24' AS `target_date`
UNION ALL SELECT '2025/08/25' AS `target_date`
) AS `d`
▼実行結果
+-------------+-------+------------+
| target_date | youbi | monday |
+-------------+-------+------------+
| 2025/08/17 | 日 | 2025/08/11 |
| 2025/08/18 | 月 | 2025/08/18 |
| 2025/08/19 | 火 | 2025/08/18 |
| 2025/08/20 | 水 | 2025/08/18 |
| 2025/08/21 | 木 | 2025/08/18 |
| 2025/08/22 | 金 | 2025/08/18 |
| 2025/08/23 | 土 | 2025/08/18 |
| 2025/08/24 | 日 | 2025/08/18 |
| 2025/08/25 | 月 | 2025/08/25 |
+-------------+-------+------------+
9 rows in set (0.001 sec)
日付の所属月の月初日を求める
書くまでもないとは思うのですが手順として書いておきます。
▼対応方針
DATE_FORMAT()関数で日の箇所を「01」にするだけですね。
▼SQL
SELECT
target_date,
DATE_FORMAT(target_date, '%Y/%m/01') AS `first_day`
FROM
(
SELECT '2025/07/31' AS `target_date`
UNION ALL SELECT '2025/08/23' AS `target_date`
UNION ALL SELECT '2025/09/01' AS `target_date`
) AS `d`
▼実行結果
+-------------+------------+
| target_date | first_day |
+-------------+------------+
| 2025/07/31 | 2025/07/01 |
| 2025/08/23 | 2025/08/01 |
| 2025/09/01 | 2025/09/01 |
+-------------+------------+
3 rows in set (0.001 sec)
日付の所属月の末日を求める
これも関数一発なので特に書く必要はないと思いますが手順として。
▼対応方針
LAST_DAY()関数を使って対象日付の所属月の末日を求める。
▼SQL
SELECT
d.target_date,
LAST_DAY(d.target_date) AS `last_day`
FROM
(
SELECT '2025/07/31' AS `target_date`
UNION ALL SELECT '2025/08/23' AS `target_date`
UNION ALL SELECT '2025/09/01' AS `target_date`
) AS `d`
▼実行結果
+-------------+------------+
| target_date | last_day |
+-------------+------------+
| 2025/07/31 | 2025-07-31 |
| 2025/08/23 | 2025-08-31 |
| 2025/09/01 | 2025-09-30 |
+-------------+------------+
3 rows in set (0.001 sec)
日付の所属月の日付を全て表示する
特定日付の所属月の日付を全て表示してみます。
▼対応方針
特定日付を変数「target_date」にセット。
WITH RECURSIVE を使って末日まで再帰処理。
▼SQL
SET @target_date = '2025/07/07';
WITH RECURSIVE dates AS (
SELECT DATE_FORMAT(@target_date, '%Y/%m/01') AS dt
UNION ALL
SELECT
DATE_ADD(dt, INTERVAL 1 DAY)
FROM
dates
WHERE
dt < LAST_DAY(@target_date)
)
SELECT
DATE_FORMAT(dt, '%Y/%m/%d') AS `date_of_month`
FROM
dates
ORDER BY
date_of_month ASC
;
▼実行結果
+---------------+
| date_of_month |
+---------------+
| 2025/07/01 |
| 2025/07/02 |
| 2025/07/03 |
| 2025/07/04 |
| 2025/07/05 |
| 2025/07/06 |
| 2025/07/07 |
| 2025/07/08 |
| 2025/07/09 |
| 2025/07/10 |
| 2025/07/11 |
| 2025/07/12 |
| 2025/07/13 |
| 2025/07/14 |
| 2025/07/15 |
| 2025/07/16 |
| 2025/07/17 |
| 2025/07/18 |
| 2025/07/19 |
| 2025/07/20 |
| 2025/07/21 |
| 2025/07/22 |
| 2025/07/23 |
| 2025/07/24 |
| 2025/07/25 |
| 2025/07/26 |
| 2025/07/27 |
| 2025/07/28 |
| 2025/07/29 |
| 2025/07/30 |
| 2025/07/31 |
+---------------+
31 rows in set (0.001 sec)
日付の所属月のカレンダーを表示する(曜日がカラム)
これがイマイチ何の役に立つのかわかりません。
もう趣味の世界です。
▼対応方針
- 対象日付を変数「target_date」に格納
- 日付の出力書式を変数「date_format」に格納
- 非表示欄の文字列を変数「blank_day」に格納
- 曜日をカラムにする
- 日曜スタートで表示
- 日付は2桁で右寄せ表示(頭スペース埋め)
- 各日付の週番号を計算
- 週番号でGROUP BY
- 週番号昇順でソート
▼SQL
SET @target_date = '2025/07/07';
SET @date_format = '%e';
SET @blank_day = '-';
WITH RECURSIVE
dates AS (
SELECT DATE_FORMAT(@target_date, '%Y/%m/01') AS dt
UNION ALL
SELECT
DATE_ADD(dt, INTERVAL 1 DAY)
FROM
dates
WHERE
dt < LAST_DAY(@target_date)
)
SELECT
LPAD(IFNULL(MIN(CASE WHEN WEEKDAY(dt) = 6 THEN DATE_FORMAT(dt, @date_format) END), @blank_day), 2, ' ') AS '日',
LPAD(IFNULL(MIN(CASE WHEN WEEKDAY(dt) = 0 THEN DATE_FORMAT(dt, @date_format) END), @blank_day), 2, ' ') AS '月',
LPAD(IFNULL(MIN(CASE WHEN WEEKDAY(dt) = 1 THEN DATE_FORMAT(dt, @date_format) END), @blank_day), 2, ' ') AS '火',
LPAD(IFNULL(MIN(CASE WHEN WEEKDAY(dt) = 2 THEN DATE_FORMAT(dt, @date_format) END), @blank_day), 2, ' ') AS '水',
LPAD(IFNULL(MIN(CASE WHEN WEEKDAY(dt) = 3 THEN DATE_FORMAT(dt, @date_format) END), @blank_day), 2, ' ') AS '木',
LPAD(IFNULL(MIN(CASE WHEN WEEKDAY(dt) = 4 THEN DATE_FORMAT(dt, @date_format) END), @blank_day), 2, ' ') AS '金',
LPAD(IFNULL(MIN(CASE WHEN WEEKDAY(dt) = 5 THEN DATE_FORMAT(dt, @date_format) END), @blank_day), 2, ' ') AS '土'
FROM
dates
GROUP BY
FLOOR((DAY(dt) + WEEKDAY(DATE_FORMAT(dt, '%Y/%m/01'))) / 7)
ORDER BY
MIN(dt) ASC
;
▼実行結果
+------+------+------+------+------+------+------+
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
+------+------+------+------+------+------+------+
| - | - | 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | 31 | - | - |
+------+------+------+------+------+------+------+
5 rows in set (0.001 sec)
もうアホですね。
- 1
- 1
- 0
- 0


コメント