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

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

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

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

3回答

5118閲覧

【SQL,PostgreSQL】ある日の5分おきの集計を取りたい

pecchan

総合スコア555

PostgreSQL

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2018/12/14 01:22

いつもお世話になってます。
PostgreSQL-9.6.11-1、Windows10です。

以下のような「直近3日の1時間おきの集計」を取得するSQLがありました。

CREATE TABLE public.t_history ( id integer, regist_timestamp timestamp without time zone NOT NULL, regist_user character varying(50) NOT NULL, CONSTRAINT t_history_pkey PRIMARY KEY (id) )

SQL

1SELECT 2 datetable.datetime, 3 COALESCE(total.cnt, 0) as count 4FROM 5( 6 7 SELECT TO_CHAR(generate_series, 'YYYY/MM/DD HH24') as datetime 8 FROM 9 generate_series( 10 CAST(TO_CHAR(NOW() + INTERVAL '-3 day', 'YYYY/MM/DD HH24:00:00') AS timestamp), 11 CAST(TO_CHAR(NOW(), 'YYYY/MM/DD HH24:00:00') AS timestamp), 12 '1 hour' 13 ) 14) AS datetable 15 16 17LEFT JOIN 18( 19 20 SELECT 21 TO_CHAR(end_timestamp, 'YYYY/MM/DD HH24') as datetime, 22 count(*) AS cnt 23 FROM 24 ( 25 26 SELECT * FROM t_history 27 WHERE 28 29 end_timestamp >= CAST(TO_CHAR(NOW() + INTERVAL '-3 day', 'YYYY/MM/DD HH24:00:00') AS timestamp) 30 ) as source 31 32 GROUP BY datetime 33) AS total 34ON datetable.datetime = total.datetime 35 36ORDER BY datetable.datetime DESC

こちらを流用して、
・直近3日→特定の1日
・1時間おき→5分おき
に変更したいです。

下記のように日付指定を追加しましたが、絞り込み出来ませんでした。
※コメント部分

SQL

1SELECT 2 datetable.datetime, 3 COALESCE(total.cnt, 0) as count 4FROM 5( 6 7 SELECT TO_CHAR(generate_series, 'YYYY/MM/DD HH24') as datetime 8 FROM 9 generate_series( 10 CAST(TO_CHAR(NOW() + INTERVAL '-3 day', 'YYYY/MM/DD HH24:00:00') AS timestamp), 11 CAST(TO_CHAR(NOW(), 'YYYY/MM/DD HH24:00:00') AS timestamp), 12 '1 hour' 13 ) 14) AS datetable 15 16 17LEFT JOIN 18( 19 20 SELECT 21 TO_CHAR(end_timestamp, 'YYYY/MM/DD HH24') as datetime, 22 count(*) AS cnt 23 FROM 24 ( 25 26 SELECT * FROM t_history 27 WHERE 28 --日付指定追加 29 regist_timestamp = '2018/12/12' 30 --end_timestamp >= CAST(TO_CHAR(NOW() + INTERVAL '-3 day', 'YYYY/MM/DD HH24:00:00') AS timestamp) 31 ) as source 32 33 GROUP BY datetime 34) AS total 35ON datetable.datetime = total.datetime 36 37ORDER BY datetable.datetime DESC

分かる方教えていただけないでしょうか?

どうぞ宜しくお願い致します。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2018/12/14 01:53

generate_seriesを使って日付時刻を生成している箇所をどうアレンジするか曖昧なので、仕様を明確に示してください。例えば、特定の1日の0時から23時とする、とか。
guest

回答3

0

ベストアンサー

指定した日付の5分間隔のタイムテーブルを基準に、t_historyregist_timestampと結合してカウントします。

SQL

1select dt.datetime 2 , count(his.id) 3from generate_series('2018/12/12'::timestamp, '2018/12/12'::timestamp + INTERVAL '1 day', '5 minute') as dt(datetime) 4 left join t_history as his 5 on his.regist_timestamp >= dt.datetime and his.regist_timestamp < (datetime + INTERVAL '5 minute') 6group by dt.datetime

因みに、参考にしているSQLですが、NOW()を正時に変更していますが、Date型だとそれは不要です。
記述を簡潔にすると以下の様になります。

実行時の時間を軸にしているようなので、取り下げ
ついでに、元のSQLを簡潔にすると

SQL

1select dt.datetime 2 , count(his.id) 3from generate_series( 4 TO_CHAR(NOW(), 'YYYY/MM/DD HH24:00:00'):: timestamp + INTERVAL '-3 day', 5 TO_CHAR(NOW(), 'YYYY/MM/DD HH24:00:00'):: timestamp, 6 '1 hour' 7 ) as dt(datetime) 8 left join t_history as his 9 on his.end_timestamp>= dt.datetime and his.end_timestamp< (dt.datetime + INTERVAL '1 hour') 10group by dt.datetime 11

投稿2018/12/14 02:00

編集2018/12/14 04:26
sazi

総合スコア25173

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

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

pecchan

2018/12/14 03:55

有難う御座います。
guest

0

まず、regist_timestampはtimestamp型なのに、日付と比較しているので、'2018/12/12 00:00:00.000'のデータとしか一致しません。
regist_timestampをdate型にキャストして比較しましょう。

次に5分おきの判断ですが、時間と違い範囲(0~5、6~10、11~15、...)で検索する必要があります。

投稿2018/12/14 01:58

kasa0

総合スコア578

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

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

pecchan

2018/12/14 03:56

型の違い、気付きませんでした。有難う御座います。
guest

0

パット見でわかる文法エラー。
regist_timestamp = '2018/12/12'
じゃなくて
regist_timestamp = '2018-12-12'::timestamp
かなと。

それと、

sql

1 SELECT TO_CHAR(generate_series, 'YYYY/MM/DD HH24:MI:00') as datetime 2 FROM 3 generate_series( 4 '2018-12-12'::timestamp, 5 '2018-12-12'::timestamp + '1 day'::interval, 6 '5 minutes' 7 )

とか。

投稿2018/12/14 01:54

編集2018/12/14 01:58
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

pecchan

2018/12/14 03:57

regist_timestamp = '2018-12-12'::timestamp 上記の方法も初めて知りました。 有難う御座います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問