下記のような素データから結果を取得したいです。
具体例には、土日祝日が抜けた、営業日ベースの休暇取得日の羅列データから連続した期間(開始日、終了日)を計算したいです。
結果
氏名 開始日 終了日
あああ 2022/8/4 2022/8/10
あああ 2022/8/29 2022/8/30
あああ 2022/9/6 2022/9/12
素データ
氏名 休暇取得日
あああ 2022/8/4
あああ 2022/8/5
あああ 2022/8/8
あああ 2022/8/9
あああ 2022/8/10
あああ 2022/8/29
あああ 2022/8/30
あああ 2022/9/6
あああ 2022/9/7
あああ 2022/9/8
あああ 2022/9/9
あああ 2022/9/12
現状、どこまでできていますか。まったく手付かずですか。
祝日はどのように判断するつもりでしょうか。
休日テーブルに格納するのでしょうか。
まずは、どこまでできているか、やったことを提示してもらえますか。
手付かずでも、どのようにするのか考えていることを提示してもらえますか。
例えば
その日が祝日かどうかを判断する方法はいろいろあるのでひとまず省略します
「存在しないデータ」を評価するのは大変です。処理中に適切に作り出す必要があります
上記例ではVBAで
終了日
として作り出してみました。処理の状況によってレコードを進めたり、足踏みしていたりと注意が必要です「休日テーブル」のような実データを用意する方向であれば、単純にテーブルをマージすれば日付が連続するデータになるのでクエリでもなんとかなるのかな?と思います。(そのために土・日の日付まで実データで保存するのはどうかと思いますが)
どうもありがとうございます。
hirotonさまにご教授いただいたコードで期待通りの結果が得られたことを確認させていただきました。
一度にあの結果セットまでできなくても良いと考えていまして、
土日祝日の存在しないデータを埋められれば、キーブレイク処理等でできないことはないかなという感じでした。
素データの対象期間内の土日はWeekday関数を使って生成し、祝日はネットでデータを取得して作成していました。
これを、対象期間のうち開始と終了で挟まれた期間のみを、土日祝日の存在しないデータを埋められれば、
と苦戦していたところでした。
まずは、いただきましたロジックをじっくり勉強させていただきます。
私の理解を超えていまして、直しどころが全然分かりませんでした。
例えば、
2022/9/16(金)休暇取得、2022/9/19(月)休暇取得があれば、9/17、9/18は休暇期間中と考え、
2022/9/16(金)休暇取得、2022/9/19(月)休暇取得がなければ、9/17、9/18は休暇期間中と考えない、
としたいと思っています。
あまり現実的ではないかもしれませんが、私の理解できる範囲では、
1.氏名が空欄のところは、開始と終了に挟まれた期間の土日祝日のデータを補完し、
2.連番を振り、
3.連番最小値が開始日、連番最大値が終了日として認識
ここまで段階的にできれば何とかなりそうなのですが、土日、祝日の実テーブルを用意するにしても、
データの補完方法が分かりません。
アドバイスいただけましたら幸いです。
氏名 休暇取得日 連番 連番最小値 連番最大値
あああ 2022/8/4 1 True
あああ 2022/8/5 2
2022/8/6 3
2022/8/7 4
あああ 2022/8/8 5
あああ 2022/8/9 6
あああ 2022/8/10 7 True
あああ 2022/8/29 1 True
あああ 2022/8/30 2 True
あああ 2022/9/6 1 True
あああ 2022/9/7 2
あああ 2022/9/8 3
あああ 2022/9/9 4
2022/9/10 5
2022/9/11 6
あああ 2022/9/12 7 True
結果テーブルを用意して、全部データ移行すれば。素データテーブルにこだわる意味はありますか?
迷走している様子を見ていると、そもそも何がやりたいのかをきちんと説明できるのか疑問です。
肝となるのは
この部分ですね
変数のつくり方(数・名前)は非常に大事で、コードが複雑化する場合は、変数が適切か見直すと良いです。今回の
終了日
もコード上では実際の終了日を指すものではなく、一時的なデータとなっています(処理の結果、正式な終了日になる仮データ)コードの処理に即して名前を付けるのであれば「
終了日となりうる日付
」で、もっと具体的に言えば「休日を考慮した連続した日付の最終日
」ですこれを使ってコードを組みなおすと
処理を丁寧に書けばこんな感じです
さて、本題です
「休日を挟んで連続していたら連続とみなす。そうでなかったら前のレコードの日付を終了日とする」ですね。上記丁寧版では無意味だった「終了日となりうる日付」と「休日を考慮した連続した日付の最終日」をきっちり分けて考えてあげればいいですね
hirotonさま、どうもありがとうございます。
結果セットとしては完璧でして、感動しています。
最後にコメントさせていただいた方法ですが、私が投稿前に考えたイメージになりますが、
段階的にでも、基幹システムから取得した素データに対して、休日データが補完できて、にフラグを立てられれば、
あとは表示の問題だけと考えておりました。
一気に結果を表示させるよりは、素データにクエリでフラグを立てて、表示変換をするほうが、
私には現実的と考えています(そもそも一気にそこまでできるのだと感動すらしているくらいでして)。
戻ってしまいますが、例えば、クエリとしてフラグなどの作業データを追加したりする方法についても、
少しアドナイスいただけましたら幸いです。
詳細な解説ありがとうございました。理解するのに1時間以上かかりました。
フォームで表示対象者を変更させたり、休職者全件レポートなども動的に生成する必要がありますので、
テーブルに書き出して、これらの機能もいちおう実装できました。
レコードの前後を比較するのはデータベースにとって苦手な処理です。複雑な処理を組むのも、その処理速度もデータベースにやらせるメリットはありません
このようなデータは、「計算で求められるデータ」であっても実データとして保存してしまうほうがシンプルに済みます
ただし、実データとして保存する場合は、それが常に最新のデータであると保証する必要があります。データの更新タイミングと、その内容を理論的に説明できるかということですね
カレンダーテーブルを作る
翌営業日の登録があるデータは連続休暇の最終日ではないので、翌営業日は何日か?という基礎データを作成します
内容は、全日付のカレンダーで、休日フラグ(土日祝日)を設けます。これで、翌営業日は「休日を除いて、対象の日付より大きく、最小の日付」として求められます。
Q素データ改
翌営業日が求められたら、翌営業日が存在するレコードは終了日ではないので、それを取り除くことにより終了日のリストを作成できます
Q終了日リスト
終了日のリストができたら、「自身の日付以上で最小の日付」が休暇期間の終了日になるので、素データのすべてのレコードに対して終了日を設定し、グループ化して休暇取得日の最小を取れば求めるデータになります
急に祝日が変わった(東京オリンピックのときとか)などに注意すれば変更することのないデータが元になるのでシンプルでしょう
また、「翌営業日」を求める計算は何度計算しても結果が変わらないのでカレンダーテーブルにフィールドを設けて保存してしまってもいいと思います
もう一つ、「休暇取得日」登録のタイミングをデータの更新タイミングとする方法を
素データに開始日を登録する
いままで「終了日」を求める方向でやっていましたが、「開始日」を求めるようにします。最終的なデータの出し方は「開始日でグループ化し、休暇取得日は最大を取る(=終了日になる)」です
開始日を記録する理由は、問題の性質上「休暇取得日」が登録されると前のレコードにわたって終了日が変わる可能性があり、終了日を管理するのは手間が多いからです
「休暇取得日」の登録がしっかり管理されていれば(そのタイミングでしっかり更新処理ができれば)独立したデータ(カレンダーテーブル)の管理もいらないシンプルなシステムが作れます
hirotonさま
どうもありがとうございます。なるほどです、大変勉強になります。
カレンダーの実データを作ってしまうのですね。
開始日基準ですか、おっしゃる通りですね。
終了日はデータの追加更新の都度、変わる可能性があります。
ひとまず、いただい情報をもとに、実カレンダーで同様の結果が得られるようにトライしてみます。
ありがとうございます。クエリを順番に作成していったらできました。
感動です。じっくり勉強させていただきます。