Microsoft Access 掲示板

「開始時刻」と「終了時刻」を同内容であれば集約したい

10 コメント
views
4 フォロー

お世話になります。
「開始時刻」と「終了時刻」を同内容であれば集約したく、いろいろとサイトを巡って調べていると、下記のサイトにたどりつきました。
「開始日付」と「終了日付」で管理しているデータをSQLで期間集約するには?

まさにこれと同じ作業をしたいのですが、上記サイトでは Accessを使用していません。
Accessでやろうと試みましたが、Window関数(分析関数)というものが分からず、全く同じやり方では厳しいのではと悩んでいます。
この作業を別の方法を用いてでもAccessで行いたいですが可能でしょうか?
ご教授の程よろしくお願い致します。

mama163
作成: 2020/03/10 (火) 13:43:02
最終更新: 2020/03/10 (火) 13:43:54
通報 ...
1

実際のテーブル名、フィールド(名前、データ型)、主キー設定をとりあえず提示してください。
また、

「開始時刻」と「終了時刻」を同内容であれば集約したく
の部分を実際のデータ例で詳細に説明してもらえますか。

例えば、同内容(連続データ)と判断する基準は、秒まで完全に一致する場合か、あるいは、隣接しているなら連続データと判断するのか。あるいは、重なっている場合があるなら、それも連続データとするのか、など。

2
mama163 2020/03/10 (火) 15:23:38 41881@32811

早々のご返信ありがとうございます。
内容不足で申し訳ございません。

テーブル名:T_日報マスタ
主務キー:ID

ID日付内容開始終了
12020/3/10移動7:009:00
22020/3/10作業9:0010:00
32020/3/10作業10:0015:00
42020/3/10移動15:0016:00
52020/3/10作業16:0018:00
62020/3/12作業8:4517:00
72020/3/13作業8:4512:00
82020/3/13作業12:0017:00
92020/3/14移動8:4510:00
102020/3/14作業10:0017:00

これを
クエリ名:Q_日報マスタ

日付内容開始終了
2020/3/10移動7:009:00
2020/3/10作業9:0015:00
2020/3/10移動15:0016:00
2020/3/10作業16:0018:00
2020/3/12作業8:4517:00
2020/3/13作業8:4517:00
2020/3/14移動8:4510:00
2020/3/14作業10:0017:00

のような形にしたいと思っています。
前提として
同じ日付の場合、ID番号の「終了」とID番号+1の「開始」は同じ時刻が入ります。

やりたい作業:ID2、3が同じ日付(3/10)、同内容(作業)で9:00~10:00、10:00~15:00と続いているので9:00~15:00にまとめたい
ただし、ID4が違う作業(15:00~16:00に「移動」)なのでID5はまとめない

同内容の判断基準は、同じ日付、作業 でID番号の「終了」とID番号+1の「開始」の時間:分 が一致する場合です。

ご確認よろしくお願い致します。

3

連続するデータが2つのまでなら、下記のような二段階のクエリでできそうです。

クエリ名 Q_日報1

SELECT
 T1.ID, T1.日付, T1.内容, T1.開始, T2.終了
FROM
 T_日報マスタ AS T1 INNER JOIN T_日報マスタ AS T2
 ON (T1.日付 = T2.日付) AND (T1.内容 = T2.内容) AND (T1.終了 = T2.開始) ;

クエリ名 Q_日報マスタ

SELECT
 T1.日付, T1.内容, Min(T1.開始) AS 開始, Nz([Q1].[終了],[T1].[終了]) AS 終了
FROM
 T_日報マスタ AS T1 LEFT JOIN Q_日報1 AS Q1
 ON (T1.開始 = Q1.開始) AND (T1.内容 = Q1.内容) AND (T1.日付 = Q1.日付)
GROUP BY
 T1.日付, T1.内容, Nz([Q1].[終了],[T1].[終了])
ORDER BY
 T1.日付, Min(T1.開始);

3つ以上連続する場合があるとちょっと面倒そうです。

4
mama163 2020/03/10 (火) 17:48:56 41881@32811

早々のご返信ありがとうございます。
取り急ぎ、3つ以上連続する場合もあります。
省略してしまいましたが、テーブルには下記のような内訳あります。
内容によって3つ以上になる場合があります。サンプルが情報不足で申し訳ございません…

日付内容内訳開始終了
2020/3/10作業設計9:0010:00
2020/3/10作業組立10:0011:00
2020/3/10作業出荷11:0012:00

まずはご返信された内容にて確認させていただきます。

5
mama163 2020/03/10 (火) 19:33:52 41881@32811 >> 4

追記です。
ご教授していただいた内容で、2つまでなら希望通りのクエリが作成できました。ありがとうございます。
ですが確かに3つ以上はうまくいきません。別の方法が必要なのですね。

同じ日付で内容が連続した場合、そのレコードの中から開始の最小値と終了の最大値を取得するには・・・

6
mayu 2020/03/10 (火) 20:37:16 修正 a3615@61ad5

Window 関数は、Oracle や SQLServer など本格的なデータベースには標準で搭載されている機能ですが、
Access には移植されておらず、LAG や LEAD といった関数は、模倣するのが難しいですから
旅人算 」という手段を用いて実現する方法 をご紹介します。

手順1
hatenaさんのコンテンツで紹介されている下記の関数を使いますから
ご自身のデータベースに、モジュール( SetSequenceNumber関数 )をインポートしておいてください。
 

グループ毎連番を自動入力する関数
クエリで連番を表示する場合、DCount関数やサブクエリを利用する方法はあちこちで紹介されています。 しかし、この方法は自分より前のレコード件数をカウントするというロジックなのでレコード件数が多くなると幾何級数的に重くなります。また、グループ毎に連番を振るという仕様になると、条件式も複雑になってきます。 クエリは使わずにテーブルに連番フィールドを持たせて、そこに VBA で連番を書きこむようにすると高速...
fc2

手順2
T_日報マスタ テーブルに 数値型のフィールドを2つ追加します。
追加するフィールドの名前は

    全体連番
    グループ連番

とします。

手順3
追加した2つのフィールドに VBA で連番を振ります。
(
  ※ 全体連番には、日付 + 開始時刻 の昇順で ユニークな番号を付与します。
  ※ グループ連番には 日付・内容 を母集団とし、開始時刻の昇順で 集団内での連番を付与します。
)

Sub set_number()
    Call SetSequenceNumber("全体連番", "T_日報マスタ", , "日付,開始")
    Call SetSequenceNumber("グループ連番", "T_日報マスタ", "日付,内容", "開始")
End Sub

 
■ set_number実行前

ID日付内容開始終了全体連番グループ連番
12020/03/10移動7:00:009:00:00
22020/03/10作業9:00:0010:00:00
32020/03/10作業10:00:0011:00:00
42020/03/10移動15:00:0016:00:00
52020/03/10作業16:00:0018:00:00
62020/03/12作業8:45:0017:00:00
72020/03/13作業8:45:0012:00:00
82020/03/13作業12:00:0017:00:00
92020/03/14移動8:45:0010:00:00
102020/03/14作業10:00:0017:00:00
112020/03/10作業11:00:0012:00:00

 
■ set_number実行後

ID日付内容開始終了全体連番グループ連番
12020/03/10移動7:00:009:00:0011
22020/03/10作業9:00:0010:00:0021
32020/03/10作業10:00:0011:00:0032
42020/03/10移動15:00:0016:00:0052
52020/03/10作業16:00:0018:00:0064
62020/03/12作業8:45:0017:00:0071
72020/03/13作業8:45:0012:00:0081
82020/03/13作業12:00:0017:00:0092
92020/03/14移動8:45:0010:00:00101
102020/03/14作業10:00:0017:00:00111
112020/03/10作業11:00:0012:00:0043
7

( 続き )

ここまで出来たら、あとは単純な集計クエリで表現可能です。

■ SQL

SELECT 日付
     , 内容
     , Min( t.開始 ) As 開始
     , Max( t.終了 ) As 終了
FROM T_日報マスタ t
GROUP BY 日付
       , 内容
       , 全体連番 - グループ連番
ORDER BY 日付
       , Min( 開始 ) ;

 
■ 結果

日付内容開始終了
2020/03/10移動7:00:009:00:00
2020/03/10作業9:00:0012:00:00
2020/03/10移動15:00:0016:00:00
2020/03/10作業16:00:0018:00:00
2020/03/12作業8:45:0017:00:00
2020/03/13作業8:45:0017:00:00
2020/03/14移動8:45:0010:00:00
2020/03/14作業10:00:0017:00:00
8
mama163 2020/03/11 (水) 08:28:40 41881@32811

mayu様ご返信ありがとうございます。
Window 関数についてや詳細な手順まで載せて頂き大変感謝致します。
(旅人算、面白い名前ですね)

まずはご教授していただいた内容にてトライしてみます。
もし不明点あれば恐縮ですがまた質問させていただきます。

9
mama163 2020/03/11 (水) 11:05:28 41881@32811 >> 8

追記です。
手順通り行ったところ、まさに希望通りの表現ができました!

グループ毎連番の記事は以前拝見しましたが、この作業に応用できるという発想には全く至りませんでした。
それに 全体連番 - グループ連番 でグループを作るとは・・・
これならレコード件数が増えても処理が重くなることがなさそうなので二重に助かります。

ご教授いただきありがとうございました。