質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
DateTime

多くのプログラミング言語におけるDateTimeオブジェクトは、日付と時間に関する演算と出力を行います。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Q&A

解決済

2回答

809閲覧

SQLでの行単位での値の比較と抽出方法についての質問です

mikan_s4n

総合スコア377

DateTime

多くのプログラミング言語におけるDateTimeオブジェクトは、日付と時間に関する演算と出力を行います。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

0グッド

0クリップ

投稿2018/08/10 02:18

編集2018/08/10 02:44

Postgresql での質問です。
現在、以下のようなDB値から、15分単位で連続する時間を一塊として抽出したいです。
抽出後のイメージとなるようにSQLのみで実装出来れば非常に嬉しいのですが、行単位で比較するというところで四苦八苦しています。
仕様上、DBには以下の日付と時間はCharで入ってますので、もしかしたらSQL上でtimestampに変換した方がいいのでしょうか。
基本的にはSQL単体で実装するという要件のため、SQLのサンプルや実装方法の提案等頂けたら助かります。

DB値

日付時間
201808010800
201808010815
201808010830
201808010845
201808010900
201808011200
201808011215
201808011230
201808011800
201808011815
201808011830

抽出後のイメージ

日付開始終了
2018080108000900
2018080112001230
2018080118001830

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

lag()とlead()を使用して連続しているかどうかを判断します。
見直せば、もう少しコストは下げられるかもしれません。
時間計算の為にCASTしているので、castが不要になれば若干コストは下がると思います。

SQL

1with iv as ( 2 select *, case when 起点 then 時間 end as 開始, case when 終点 then 時間 end as 終了 3 from ( 4 select * 5 , coalesce((lag(時間) over(order by 日付, 時間)::time + '15 minutes'!=時間::time), true) as 起点 6 , coalesce((lead(時間) over(order by 日付, 時間)::time + '-15 minutes'!=時間::time), true) as 終点 7 from Table1 8 ) lv1 9) 10select distinct 日付 11 , (select max(開始) from iv where 日付=t1.日付 and 時間<=t1.時間) 開始 12 , (select min(終了) from iv where 日付=t1.日付 and 時間>=t1.時間) 終了 13from iv t1 14order by 1, 2

DATA

1CREATE TABLE Table1 2 (日付 char(8), 時間 char(4)) 3; 4INSERT INTO Table1 5 (日付, 時間) 6VALUES 7 (20180801, '0800'), 8 (20180801, '0815'), 9 (20180801, '0830'), 10 (20180801, '0845'), 11 (20180801, '0900'), 12 (20180801, '1200'), 13 (20180801, '1215'), 14 (20180801, '1230'), 15 (20180801, '1800'), 16 (20180801, '1815'), 17 (20180801, '1830') 18;

投稿2018/08/10 04:04

編集2018/08/10 04:08
sazi

総合スコア25138

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mikan_s4n

2018/08/10 05:04

大変分かりやすいサンプルを頂き、ありがとうございます。 lagとleadを使って行単位で計算を行っている感じでしょうか。 CASTに関してはコスト削減の観点から私もそうしたいのですが、既存DBの変更は不可とのことでそのままとなりそうです……。 おかげさまで問題解決できそうです。 本当にありがとうございました!
guest

0

可能ならtimestamp型あるいはtimestamp with time zone型を活用してください。
ある瞬間の時刻が一発で定まりその日時よりも前か後ろかの判定がしやすくなります。
日付をまたぐ前後を比較するのも楽になります。

投稿2018/08/10 02:30

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問