基幹人事システムから発令に基づくアクション一覧を取得し、
組織の在籍期間を算定しようと思っています。
キーブレイク処理ができなくてクエリでなんとかできないかとここまでやりましたが、
最大、最小で抽出をしているため、出戻りの組織(人事)があると崩れてしまうことが判明しました。
⇒赤色でハイライトした箇所が正しく拾えず、黄色の箇所が結果として合っている
⇒出戻りの、更に、出戻りもある可能性もあります
お知恵を拝借できますでしょうか。
アクションテーブルに対し1~4のクエリを作成(4を最終形)
1.氏名、組織、開始日、終了日でグループ化
2.氏名、組織、開始日の最小値でグループ化
3.氏名、組織、開始日の最大値でグループ化
4.クエリ1の氏名、開始日とクエリ2の氏名と開始日の最小値
クエリ1の氏名、終了日とクエリ3の氏名と開始日の最大値
アクションテーブル
アクション 発令日 開始日 終了日 組織名
採用 20140401 20140401 20140525 人事
出向開始 20140526 20140526 20140531 人事
職種変更 20140601 20140601 20150331 人事
出向終了 20151101 20151101 20170930 経営企画
職種変更 20171001 20171001 20210331 法務
20200801 20171001 20210331 法務
出向開始 20210401 20210401 20220331 人事
職種変更 20220401 20220401 20230331 総務
出向先変更 20230401 20230401 99991231 総務
クエリ4
氏名 開始日 終了日 組織名
青山 太郎 20140401 人事
青山 太郎 人事
青山 太郎 20151031 人事
青山 太郎 20151101 20170930 経営企画
青山 太郎 20171001 20210331 法務
青山 太郎 20210401 20220331 人事
青山 太郎 20220401 総務
青山 太郎 99991231 総務
基幹人事システムならば、社員所属テーブルがあるはずですが?何故、クエリで捻り出さないといけないの?
普通そう思いますよね。
基幹システムが全く機能していなくて、所属歴が取れないので苦肉の策です。
日付が連続するとしているならば、各組織での開始日を、不要なレコードを削除することによって求めることができます。各レコードに於いて、「『開始日』の前日が終了日であるレコード」の組織が同じ組織であれば、そのレコードは連続した組織のデータであり、開始日として不要なデータとなります
そのようなデータであるかどうかを求める場合
このような計算をすると、各組織の開始日に当たるレコードだけ「0」の結果が得られます
※質問中のデータの場合、6行目(アクションが空白のレコード)も抽出されます
「開始日だけ」のデータが出来上がれば、「次のレコードの開始日の前日」が「終了日」です
職種変更 20171001 20171001 20210331 法務
20200801 20171001 20210331 法務
上記の部分は、下記のものの転記間違いでしょうか。
職種変更 20171001 20171001 20200731 法務
20200801 20200801 20210331 法務
あと、
開始日 終了日 組織名
20140401 20140525 人事
20140526 20140531 人事
上記のように、終了日と次のレコードの開始日が20140525→20140526 というように連続していたら、一つの在籍期間として扱うということでしょうか。
クエリの最終出力フォーマットは、下記のような感じにですか。
氏名 開始日 終了日 組織名
青山 太郎 20140401 20151031 人事
青山 太郎 20151101 20170930 経営企画
青山 太郎 20171001 20210331 法務
青山 太郎 20210401 20220331 人事
青山 太郎 20220401 99991231 総務
それとも質問のように、空欄も必要なのですか。
hiroton さま
ありがとうございます。
なるほどです。こんな考え方があるのですね。
1点だけ不備がありまして、赤のところが0,1逆になりました。
氏名 開始日 終了日 組織名 判定フラグ
青山 太郎 20140401 20140525 人事 0
青山 太郎 20140526 20140531 人事 1
青山 太郎 20140601 20150331 人事 1
青山 太郎 20150401 20170930 経営企画 0
青山 太郎 20171001 20210331 法務 0
青山 太郎 20210401 20220331 総務 0
青山 太郎 20220401 20230331 総務 0
青山 太郎 20230401 99991231 総務 1
想定しているデータは>> 3の通りですが、補足しているようにデータによっては他の条件を検討する必要がでます
また、終了日を含めて一つの結果にするにはそれなりのクエリ(計算)が必要になります
質問中には「総務」のレコードは2件しかありませんので、途中結果であれ「総務」が3レコードになるのはどこかに間違いがあるのでしょう
hirotonの提案は1発で開始日、終了日両方合わせたような結果が出るようなものではないので、元データと、どのようなクエリを組んだのか確認してみてください
氏名 開始日 終了日 組織名 判定フラグ
青山 太郎 20140401 20140525 人事 0
青山 太郎 20140526 20140531 人事 1
青山 太郎 20140601 20150331 人事 1
青山 太郎 20150401 20170930 経営企画 0
青山 太郎 20171001 20210331 法務 0
青山 太郎 20210401 20220331 人事 0
青山 太郎 20220401 20230331 総務 0
青山 太郎 20230401 99991231 総務 1
失礼いたしました、転記ミスです。
他の条件も検討する必要があるとのことですね。
hatenaさま
ありがとうございます。
こちらで正しいです。アクションが空白のデータもありますし、
アクション違いで、複数の同一組織、氏名のレコードは存在します。
職種変更 20171001 20171001 20210331 法務
20200801 20171001 20210331 法務
おっしゃる通り、こちらが正解です。
氏名 開始日 終了日 組織名
青山 太郎 20140401 20151031 人事
青山 太郎 20151101 20170930 経営企画
青山 太郎 20171001 20210331 法務
青山 太郎 20210401 20220331 人事
青山 太郎 20220401 99991231 総務
方法は色々とありますけど、SQLのサンプルを載せておきます
■アクションテーブル
■SQL
■結果
mayuさま
ありがとうございます。
これすごいですね。
SQLでここまできるとは。
結果セットも3万レコードくらいできるのですが、パフォーマンスも高いです。
SQLもいいのですが複雑になるので、私がするなら、メンテナンス性とパフォーマンスを考慮して、
テーブルに在籍期間判定用のフィールドを追加して、
VBA(DAO)でそこに在籍期間ごとの連番を入力していくようにするかな。
上記の実行結果
SQL
SQL出力結果
終了日と次のレコードの開始日の連続性は考慮していないので、もし、連続しない(例えば休職とか)場合があるなら、
VBAにその条件判断を追加する必要はあります。
hatenaさま
ありがとうございます。
私もレコードセットで回してキーブレイク処理で、
判定フラグを立てる方法を試行錯誤していたのですが、
どうしてもできずにいたところでした。
まずは、じっくり内容確認させていただきます。
ロジックおよび動作確認できました。
当初はDAOによるキーブレイク処理を試みましたが、
最大、最小の日付を取ろうとして、何度も書いてもダメでした。
hatenaさまのロジックは、2段階になっていて、
なるほどと思いました。
どうもありがとうございました。
こちらのスレッドでアドレスいただいた者です。
ベースになるデータの仕様が少し変わりまして、開始日・終了日を持たず、
発令日(=開始日)のみしか持たないデータソースを使うこととなりました。
SetRenban関数にて在籍期間Noをふり、開始日および終了日はSQLで在籍期間NoのMin、Max
にて計算するというものを実装しています。
今回、ご相談させていただきたいのは、開始日は在籍期間NoのMinで良いのですが、
終了日が、理論上は[在籍期間No] + 1のMinの前日となると思っていますが、
私ができる初歩的なレベルですと、もうひとつクエリを作って、両者を結合させるとかになります。
このあたりの実装でご相談させてください。
[在籍期間No]をひとつずらして結合させるところができずにいます。
サンプルを載せておきます
最初に SetSequenceNumber関数 をデータベースにインポートして
利用可能な状態にしておきましょう
■DDL
■データ例 (連番付与前)
■グループ連番の付与
■データ例 (連番付与後)
(続き)
■DML
■結果
新しい質問を立てるのはどうでしょう?
主キーと関連するテーブルを過不足なく提示したり、スクショを提示したりするのがおすすめです。
アクションテーブルに失効日のフィールドを追加しておいて、SetRenban関数のループ内で発行日の前日を前レコードの失効日に代入するという処理を追加すればどうでしょう。
Mayuさま
どうもありがとうございます。
SetSequenceNumber関数、これは凄いものですね!
今後、使えるようにしておきたいです。
私がやったものとは格段に改善しました。
Hatenaさま
ありがとうございます。
>アクションテーブルに失効日のフィールドを追加しておいて、SetRenban関数のループ内で発行日の前日を前レコードの失効>日に代入するという処理を追加すればどうでしょう。
movePreviousとかで一旦戻って、Editすることができるんですね。
正直知りませんでした。今回、こちらのほうほうで完璧にできました。
今回、組織コードというおおくくりの組織の配下に、部門、部署というレベルがありまして、
表示する際は、氏名と開始日をもとに、所属歴を参照しては以下組織を持ってきていたのですが、
同じ在籍期間Noでの期間が長いと組織名称が変わっていたりして、終了時点の組織名称を参照する
方法に苦心していましたが、グループ内採番の日付Max値のデータを保持するクエリを作成して、
これを参照することで、Mayuさまのロジックを使わせていただき、なんとかこちらも対応できました。
どうもありがとうございました。
対象組織の在籍期間Noごとに、役職・職種を持っているのですが、
単純に最新の役職を持つクエリ、最新の職種を持つクエリを作成
(それぞれのクエリで、在籍期間Noでグループ化して、役職・職種を先頭(最後)で抽出)
したものを、こちらのクエリから参照する方法もありますね(全くスマートではないですが)。
SELECT t.氏名, t.組織名, Min(t.発令日) AS 開始日, Max(t.終了日) AS 終了日
FROM アクションテーブル As t
GROUP BY t.氏名, t.組織名, t.在籍期間No
ORDER BY t.氏名, t.在籍期間No;