documents:proglang:sql:sql-0009
差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン | |||
| documents:proglang:sql:sql-0009 [2026/05/08 12:19] – ↷ documents:database:sql-0009 から documents:proglang:sql:sql-0009 へページを移動しました。 k896951 | documents:proglang:sql:sql-0009 [2026/05/16 11:36] (現在) – [SQLで時間の集計を行う] k896951 | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| + | ====== 004.SQLで時間の集計を行う ====== | ||
| + | |||
| + | 2017年10月24日\\ | ||
| + | ちょっと調べものしてしまったので自分用メモ。 | ||
| + | |||
| + | |||
| + | ===== 処理対象データ ===== | ||
| + | |||
| + | PostgreSQLに以下のデータがある。 | ||
| + | |||
| + | <code sql> | ||
| + | $ psql -h dbsvr05 kamonohashi kamo | ||
| + | psql (9.5.9, サーバー 9.6.1) | ||
| + | WARNING: psql major version 9.5, server major version 9.6. | ||
| + | Some psql features might not work. | ||
| + | " | ||
| + | |||
| + | kamonohashi=> | ||
| + | | ||
| + | 列 | 型 | 修飾語 | ||
| + | ------+----------------------+---------- | ||
| + | | ||
| + | | ||
| + | time | character varying(5) | | ||
| + | インデックス: | ||
| + | " | ||
| + | |||
| + | kamonohashi=> | ||
| + | id | grp | time | ||
| + | ----+-----+------- | ||
| + | 1 | ca1 | 08:00 | ||
| + | 2 | ca1 | 07:30 | ||
| + | 5 | ca1 | 07:15 | ||
| + | 3 | ca2 | 07:55 | ||
| + | 10 | ca2 | 07:50 | ||
| + | 11 | ca2 | 08:10 | ||
| + | 4 | ca3 | | ||
| + | 8 | ca3 | 20:70 | ||
| + | 21 | ca3 | 27:50 | ||
| + | 23 | ca3 | aa:bb | ||
| + | 15 | ca4 | 48:30 | ||
| + | 22 | ca4 | 67:50 | ||
| + | (12 行) | ||
| + | |||
| + | kamonohashi=> | ||
| + | </ | ||
| + | |||
| + | |||
| + | これを集計して以下の結果を得たい。 | ||
| + | |||
| + | ^ grp ^ time ^ | ||
| + | | ca1 | 22:45 | | ||
| + | | ca2 | 23:55 | | ||
| + | | ca3 | 27:50 | | ||
| + | | ca4 | 99:99 | | ||
| + | |||
| + | 項目timeは | ||
| + | * HH: | ||
| + | * MMは0~59、HHは0~99の範囲。 | ||
| + | * 形式が正しくないものもある。これは計算対象外。 | ||
| + | |||
| + | また、 | ||
| + | * 集計結果が99: | ||
| + | |||
| + | ===== 形式不正の確認 ===== | ||
| + | |||
| + | |||
| + | 項目timeの形式は SIMILAR TO 演算子で検証する。最近のバージョンのSQL Serverだと、通常の Like 演算子で正規表現が使える模様。OracleだとREGEXP_LIKE()関数で正規表現が扱える。 | ||
| + | |||
| + | 以下エラー行は(' | ||
| + | <code sql> | ||
| + | kamonohashi=> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | err | id | grp | time | ||
| + | -----+----+-----+------- | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | 10 | ca2 | 07:50 | ||
| + | | 11 | ca2 | 08:10 | ||
| + | | ||
| + | | ||
| + | | 21 | ca3 | 27:50 | ||
| + | | ||
| + | | 15 | ca4 | 48:30 | ||
| + | | 22 | ca4 | 67:50 | ||
| + | (12 行) | ||
| + | |||
| + | kamonohashi=> | ||
| + | </ | ||
| + | |||
| + | ===== HH: | ||
| + | |||
| + | エラーが無いHH: | ||
| + | HH部分は" | ||
| + | HH × 60 + MM = 分単位 | ||
| + | |||
| + | <code sql> | ||
| + | kamonohashi=> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | id | grp | time_mins | ||
| + | ----+-----+----------- | ||
| + | 1 | ca1 | 480 | ||
| + | 2 | ca1 | 450 | ||
| + | 5 | ca1 | 435 | ||
| + | 10 | ca2 | 470 | ||
| + | 11 | ca2 | 490 | ||
| + | 3 | ca2 | 475 | ||
| + | 21 | ca3 | 1670 | ||
| + | 4 | ca3 | 0 | ||
| + | 23 | ca3 | 0 | ||
| + | 22 | ca4 | 4070 | ||
| + | 15 | ca4 | 2910 | ||
| + | 8 | ca3 | 0 | ||
| + | (12 行) | ||
| + | |||
| + | kamonohashi=> | ||
| + | </ | ||
| + | |||
| + | 上記を項目grpで集計すれば以下となる。 | ||
| + | |||
| + | <code sql> | ||
| + | kamonohashi=> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi(> | ||
| + | kamonohashi(> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | grp | time_mins | ||
| + | -----+----------- | ||
| + | ca1 | 1365 | ||
| + | ca2 | 1435 | ||
| + | ca3 | 1670 | ||
| + | ca4 | 6980 | ||
| + | (4 行) | ||
| + | |||
| + | kamonohashi=> | ||
| + | </ | ||
| + | |||
| + | ===== 集計結果をHH: | ||
| + | |||
| + | 集計後、分単位を再度HH: | ||
| + | HH = MINS ÷ 60 の商 | ||
| + | MM = MINS ÷ 60 の余り | ||
| + | となるので、この値を整形して文字列に落とせばいい。 | ||
| + | |||
| + | 5999は | ||
| + | 99 × 60 + 59 = 5,940 + 59 = 5,999 | ||
| + | でHH: | ||
| + | |||
| + | PostgreSQLやSQL Serverでは整数型を除算した結果は整数型になる。Oracleは型が変換されて実数型になるかもしれない。小数点以下を切り捨てするTRUNC()関数、剰余を求めるMOD()関数、を使う必要がある。 | ||
| + | <code sql> | ||
| + | kamonohashi=> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | kamonohashi(> | ||
| + | kamonohashi(> | ||
| + | kamonohashi(> | ||
| + | kamonohashi(> | ||
| + | kamonohashi(> | ||
| + | kamonohashi(> | ||
| + | kamonohashi(> | ||
| + | kamonohashi(> | ||
| + | kamonohashi(> | ||
| + | kamonohashi-> | ||
| + | kamonohashi-> | ||
| + | grp | time_mins | time | ||
| + | -----+-----------+------- | ||
| + | ca1 | 1365 | 22:45 | ||
| + | ca2 | 1435 | 23:55 | ||
| + | ca3 | 1670 | 27:50 | ||
| + | ca4 | 6980 | 99:99 | ||
| + | (4 行) | ||
| + | |||
| + | kamonohashi=> | ||
| + | </ | ||
| + | |||
| + | ===== 注意 ===== | ||
| + | |||
| + | 分単位を INTEGER型で扱っている。集計結果がINTEGER型の最大値を超えるとエラーになるので注意が必要。 | ||
| + | |||
| + | INTEGER型最大値が 2, | ||
| + | |||
| + | * 2, | ||
| + | * 35, | ||
| + | * 1, | ||
| + | |||
| + | 扱う時間の性格性質によっては、ここで上げた処理方法は使えない。 | ||
| + | |||
| + | ===== 追記:SQL Server LocalDBで試してみる ===== | ||
| + | |||
| + | SQL Serverの真っ当なインスタンスを作るの面倒なんで、SQLServer LocalDBを使って確認する。 | ||
| + | |||
| + | ==== 下準備 ==== | ||
| + | |||
| + | |||
| + | インスタンスを作ってデータベースを作ってテーブル作ってデータをインサートします。 | ||
| + | <code sql> | ||
| + | C: | ||
| + | LocalDB インスタンス " | ||
| + | |||
| + | C: | ||
| + | LocalDB インスタンス " | ||
| + | |||
| + | C: | ||
| + | 名前: | ||
| + | バージョン: | ||
| + | 共有名: | ||
| + | 所有者: | ||
| + | 自動作成: | ||
| + | 状態: | ||
| + | 前回の開始時刻: | ||
| + | インスタンス パイプ名: | ||
| + | |||
| + | C: | ||
| + | 1> select name from sys.databases | ||
| + | 2> go | ||
| + | name | ||
| + | -------------------------------------------------------------------------------------------------------------------------------- | ||
| + | master | ||
| + | tempdb | ||
| + | model | ||
| + | msdb | ||
| + | |||
| + | (4 行処理されました) | ||
| + | 1> create database kamo | ||
| + | 2> go | ||
| + | 1> use kamo | ||
| + | 2> go | ||
| + | Changed database context to ' | ||
| + | 1> create table timelog( | ||
| + | 2> | ||
| + | 3> ,grp varchar(3) | ||
| + | 4> ,time varchar(5) | ||
| + | 5> ) | ||
| + | 6> go | ||
| + | 1> insert into timelog values( 1,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values( 2,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values( 5,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values(10,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values(11,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values( 3,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values(21,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values( 4,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values(23,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values(22,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values(15,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> insert into timelog values( 8,' | ||
| + | 2> go | ||
| + | |||
| + | (1 行処理されました) | ||
| + | 1> select * from timelog order by grp,id | ||
| + | 2> go | ||
| + | id grp time | ||
| + | ----------- --- ----- | ||
| + | 1 ca1 08:00 | ||
| + | 2 ca1 07:30 | ||
| + | 5 ca1 07:15 | ||
| + | 3 ca2 07:55 | ||
| + | 10 ca2 07:50 | ||
| + | 11 ca2 08:10 | ||
| + | 4 ca3 NULL | ||
| + | 8 ca3 20:70 | ||
| + | 21 ca3 27:50 | ||
| + | 23 ca3 aa:bb | ||
| + | 15 ca4 48:30 | ||
| + | 22 ca4 67:50 | ||
| + | |||
| + | (12 行処理されました) | ||
| + | 1> | ||
| + | </ | ||
| + | |||
| + | ==== LIKEで正規表現が使えるか確認 ==== | ||
| + | |||
| + | LIKE演算子で正規表現が使えました。 | ||
| + | |||
| + | <code sql> | ||
| + | 1> select | ||
| + | 2> case when [time] LIKE ' | ||
| + | 3> ,[id] | ||
| + | 4> ,[grp] | ||
| + | 5> ,[time] | ||
| + | 6> from | ||
| + | 7> | ||
| + | 8> order by [grp],[id] | ||
| + | 9> go | ||
| + | err id grp time | ||
| + | --- ----------- --- ----- | ||
| + | NUL 1 ca1 08:00 | ||
| + | NUL 2 ca1 07:30 | ||
| + | NUL 5 ca1 07:15 | ||
| + | NUL 3 ca2 07:55 | ||
| + | NUL 10 ca2 07:50 | ||
| + | NUL 11 ca2 08:10 | ||
| + | E 4 ca3 NULL | ||
| + | E 8 ca3 20:70 | ||
| + | NUL 21 ca3 27:50 | ||
| + | E 23 ca3 aa:bb | ||
| + | NUL 15 ca4 48:30 | ||
| + | NUL 22 ca4 67:50 | ||
| + | |||
| + | (12 行処理されました) | ||
| + | 1> | ||
| + | </ | ||
| + | |||
| + | ==== 集計してみる ==== | ||
| + | |||
| + | 集計結果を" | ||
| + | |||
| + | <code sql> | ||
| + | 1> select | ||
| + | 2> | ||
| + | 3> , | ||
| + | 4> ,cast(case when 5999 < mt.[time_mins] | ||
| + | 5> then ' | ||
| + | 6> else format(mt.[time_mins] / 60, ' | ||
| + | 7> from | ||
| + | 8> ( | ||
| + | 9> | ||
| + | 10> | ||
| + | 11> | ||
| + | 12> | ||
| + | 13> | ||
| + | 14> | ||
| + | 15> | ||
| + | 16> | ||
| + | 17> ) mt | ||
| + | 18> order by mt.[grp] | ||
| + | 19> go | ||
| + | grp time_mins | ||
| + | --- ----------- ----- | ||
| + | ca1 1365 22:45 | ||
| + | ca2 1435 23:55 | ||
| + | ca3 1670 27:50 | ||
| + | ca4 6980 99:99 | ||
| + | |||
| + | (4 行処理されました) | ||
| + | 1></ | ||
| + | |||
| + | {{tag> database SQL 時間の集計 PostgreSQL SQLServer Oracle 技術資料}} | ||
documents/proglang/sql/sql-0009.txt · 最終更新: by k896951
