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

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

新規登録して質問してみよう
ただいま回答率
85.47%
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

解決済

1回答

456閲覧

betweenの範囲をサブクエリから取得して最頻値を計算したい

hideki.

総合スコア31

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クリップ

投稿2022/12/26 05:38

前提

サブクエリで得たタイムスタンプの開始と終了時刻を使って、別のテーブルのカラムの最頻値を計算して、先のサブクエリの結果に追加したいのですが、できません。

実現したいこと

質問用に2つテーブルを用意しました。
t_test_seisanテーブルはタイムスタンプとその時刻の生産品目名を記録

SQL

1CREATE TABLE IF NOT EXISTS public.t_test_seisan 2( 3 id integer, 4 ts timestamp without time zone, 5 product_nm character varying COLLATE pg_catalog."default" 6)

t_test_inspectテーブルは検査タイムスタンプと計測値v_1とV_2を記録

SQL

1CREATE TABLE IF NOT EXISTS public.t_test_inspect 2( 3 id integer, 4 ts timestamp without time zone, 5 v_1 integer, 6 v_2 integer 7)

サンプルデータ1 for t_test_seisan
1,"2022-12-20 14:15:00","品名1"
2,"2022-12-20 14:16:00","品名1"
3,"2022-12-20 14:17:00","品名1"
4,"2022-12-20 14:18:00","品名1"
5,"2022-12-20 14:19:00","品名1"
6,"2022-12-20 14:20:00","品名2"
7,"2022-12-20 14:21:00","品名2"
8,"2022-12-20 14:22:00","品名2"
9,"2022-12-20 14:23:00","品名3"
10,"2022-12-20 14:24:00","品名3"
11,"2022-12-20 14:25:00","品名3"
12,"2022-12-20 14:26:00","品名3"

サンプルデータ2 for t_test_inspect
1,2022/12/20 14:15,11 ,112
2,2022/12/20 14:16,11 ,111
3,2022/12/20 14:17,12 ,111
4,2022/12/20 14:18,12 ,111
5,2022/12/20 14:19,11 ,112
6,2022/12/20 14:20,21 ,122
7,2022/12/20 14:21,21 ,121
8,2022/12/20 14:22,22 ,121
9,2022/12/20 14:23,33 ,131
10,2022/12/20 14:24,31 ,133
11,2022/12/20 14:25,31 ,133
12,2022/12/20 14:26,32 ,131

尚、サンプルデータでは両テーブルのタイムスタンプが完全一致してますが、実際のデータではその限りではありません。
ここで、以下のQueryで生産品目毎の開始/終了時刻が得られます。

SQL

1SELECT 2 min(ts) AS from_tm, 3 max(ts) AS to_tm, 4 product_nm 5FROM t_test_seisan 6GROUP BY product_nm 7ORDER BY 1

実行結果1:
イメージ説明
また、最頻値を求める方法ですが、上図の1行目の開始/終了時刻を見て、以下のQueryを書けば、品名1の最頻値は得られるところまではできました。

SQL

1SELECT 2 mode() WITHIN GROUP (ORDER BY v_1) AS m_v_1, 3 mode() WITHIN GROUP (ORDER BY v_2) AS m_v_2 4FROM t_test_inspect 5WHERE 6 ts BETWEEN '2022-12-20 14:15:00' AND '2022-12-20 14:19:00'

実行結果2:
イメージ説明
最終的に得たいのは実行結果1の表に最頻値のm_v1とm_v2カラムを付けた表です。

試したこと

相関副問合せ(相関サブクエリ)という機能を使えば、できそうなのでネット検索して、色々試したのですが、どうしても書き方が分かりません。

補足情報(FW/ツールのバージョンなど)

PostgreSQL 10
ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

もう少しスマートな書き方がありそうですが、たとえば以下のようなクエリで実現できそうです。

SQL

1SELECT 2 MIN(A.ts) AS from_tm, 3 MAX(A.ts) AS to_tm, 4 A.product_nm, 5 (SELECT mode() WITHIN GROUP (ORDER BY B.v_1) FROM t_test_inspect AS B WHERE B.ts BETWEEN MIN(A.ts) AND MAX(A.ts)) AS m_v_1, 6 (SELECT mode() WITHIN GROUP (ORDER BY B.v_2) FROM t_test_inspect AS B WHERE B.ts BETWEEN MIN(A.ts) AND MAX(A.ts)) AS m_v_2 7FROM t_test_seisan AS A 8GROUP BY product_nm 9ORDER BY product_nm

投稿2022/12/26 12:17

neko_the_shadow

総合スコア2259

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

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

hideki.

2022/12/26 23:22

早々の回答ありがとうございます。 なるほど、このように書けば良いのですね。 WITH句やJOINを使ったり試行錯誤しましたが、エラーで実行できませんでした。 ベストアンサーにさせて頂きます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問