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

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

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

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

SQL

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

Q&A

解決済

1回答

1403閲覧

Oracle SQLで、期間が重なるレコード同士をマージしてSELECTしたい。

abcmart

総合スコア7

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

SQL

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

0グッド

0クリップ

投稿2020/05/21 09:11

編集2020/05/26 02:36

oracle sqlで、以下の実現するSQLをご教授お願い致します。

以下のようなテーブルデータがあるとき、
列3(start_date)と列4(end_date)の日時が重なる場合、
それらをマージした状態でSELECTしたいです。
この時、マージ対象となるレコードは、
列1,列2のセットが同じ値のものとします。
以下の例ですと、(C1,D1)と(C1,D2)のペア単位でマージとなります。

CREATEとINSERTはこちらです。

1CREATE TABLE KIKAN_MERGE_TB 2( 3 C1 VARCHAR2(10), 4 C2 VARCHAR2(10), 5 C3 DATE, 6 C4 DATE 7) 8 9INSERT ALL 10INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D1',TO_DATE('2020/05/01 09:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/01 12:00','YYYY/MM/DD HH24:MI')) 11INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D1',TO_DATE('2020/05/01 11:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/02 10:00','YYYY/MM/DD HH24:MI')) 12INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D1',TO_DATE('2020/04/30 07:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/03 11:00','YYYY/MM/DD HH24:MI')) 13INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D1',TO_DATE('2020/05/03 10:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/04 11:00','YYYY/MM/DD HH24:MI')) 14INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D1',TO_DATE('2020/05/04 18:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/05 11:00','YYYY/MM/DD HH24:MI')) 15INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D2',TO_DATE('2020/05/01 09:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/01 12:00','YYYY/MM/DD HH24:MI')) 16INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D2',TO_DATE('2020/05/01 12:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/02 10:00','YYYY/MM/DD HH24:MI')) 17INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D2',TO_DATE('2020/05/03 12:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/04 18:00','YYYY/MM/DD HH24:MI')) 18INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D2',TO_DATE('2020/05/05 10:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/05 15:00','YYYY/MM/DD HH24:MI')) 19INTO KIKAN_MERGE_TB(C1,C2,C3,C4) VALUES('C1','D2',TO_DATE('2020/05/05 14:00','YYYY/MM/DD HH24:MI'), TO_DATE('2020/05/05 18:00','YYYY/MM/DD HH24:MI')) 20select * from dual;

列1 列2  列3     列4
C1 D1 2020/05/01 09:00 2020/05/01 12:00
C1 D1 2020/05/01 11:00 2020/05/02 10:00
C1 D1 2020/04/30 07:00 2020/05/03 11:00
C1 D1 2020/05/03 10:00 2020/05/04 11:00
C1 D1 2020/05/04 18:00 2020/05/05 11:00 ※
C1 D2 2020/05/01 09:00 2020/05/01 12:00
C1 D2 2020/05/01 12:00 2020/05/02 10:00
C1 D2 2020/05/03 12:00 2020/05/04 18:00 ※
C1 D2 2020/05/05 10:00 2020/05/05 15:00
C1 D2 2020/05/05 14:00 2020/05/05 18:00

⇓マージ

列1 列2   列3     列4
C1 D1 2020/04/30 09:00 2020/05/04 11:00
C1 D1 2020/05/04 18:00 2020/05/05 11:00 ※
C1 D2 2020/05/01 09:00 2020/05/02 10:00
C1 D2 2020/05/03 12:00 2020/05/04 18:00 ※
C1 D2 2020/05/05 10:00 2020/05/05 18:00

※のレコードは、start_date,end_date共に、重なりがないため、そのまま表示となっております。

よろしくお願い致します。

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

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

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

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

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

abcmart

2020/05/22 01:10

コード追記しました。
KOZ6.0

2020/05/22 01:59

「「開始日付」と「終了日付」で管理しているデータをSQLで期間集約するには?」 https://qiita.com/toronya/items/8fdd99717b78ccb0bdd2 ウインドウ関数を駆使すれば可能なようです。 自分だったらストアド作って一時表に書き込むか、テーブル・ファンクションを使うと思います。
abcmart

2020/05/22 02:36

いただいたサイトページ内のページ真ん中あたりの”日付が連続しているか判定する”における、 開始差有と終了差有の'0'or'1'を決めるcase式を変える認識のように見えますが、具体的な式はわかりますか?
KOZ6.0

2020/05/22 03:13

そこはちょっと考えてみてくださいな。
abcmart

2020/05/22 10:15 編集

いただいたサイトのSQLで検証しました。 サイト内の例のようなデータを作成(start_date = end_date +1日)でまずは検証し、抽出できることは確認できました。 ※2つ目のPARTITION BYに2項目(サイト例でいう食物)を自分で付け足さないと正しい値を取らないようです。。サイトの例のSQLをそのままコピペしてもだめでした。 一方で、今回の本目的(重なるデータをまとめる)はまだ試せておりません。
Orlofsky

2020/05/22 11:37

将来のバージョンではエラーになるかもしれないので、データと書式マスクは一致させておいた方が良いのでは? TO_DATE('2020/05/01 09:00','YYYY-MM-DD HH24:MI:SS') ↓ TO_DATE('2020/05/01 09:00','YYYY/MM/DD HH24:MI')
abcmart

2020/05/25 09:45

参考にさせていただきます。
Orlofsky

2020/05/25 10:33

初心者もこの掲示板を見ることありますから、きちんと直しては? 実務でこんなコードを書いていたら信用をなくしますし。
guest

回答1

0

ベストアンサー

もっと良い方法があるような気がしますが、これでできました。
が、性能要件や開発上の制約が許すのであれば、
個人的には表関数なりSELECTするプログラム側でループするなりして
プログラムで何とかした方が良い気がします。
想定結果の1行目の列3は2020/04/30 07:00の誤りですね。

SQL

1WITH 2 T1 AS ( 3 --C1,C2ごとにC3,C4でソートした時の1行前のC3とC4を取得 4 SELECT 5 T.C1 C1 6 , T.C2 C2 7 , T.C3 C3 8 , T.C4 C4 9 , LAG(T.C3) OVER(PARTITION BY T.C1,T.C2 ORDER BY T.C3,T.C4) LAG_C3 10 , LAG(T.C4) OVER(PARTITION BY T.C1,T.C2 ORDER BY T.C3,T.C4) LAG_C4 11 FROM 12 KIKAN_MERGE_TB T 13 ) 14, T2 AS ( 15 --1行前までのC3の最小値、1行前までのC4の最大値を求める 16 SELECT 17 T1.C1 C1 18 , T1.C2 C2 19 , T1.C3 C3 20 , T1.C4 C4 21 , MIN(T1.LAG_C3) OVER(PARTITION BY T1.C1,T1.C2 ORDER BY T1.C3,T1.C4) MIN_LAG_C3 22 , MAX(T1.LAG_C4) OVER(PARTITION BY T1.C1,T1.C2 ORDER BY T1.C3,T1.C4) MAX_LAG_C4 23 FROM 24 T1 25 ) 26, T3 AS ( 27 --C3,1行前までのC3の最小値,C4,一行前までのC4の最大値を使用し、重複判定を行い、重複していなければカウントアップする(GRP_KEY) 28 SELECT 29 T2.C1 C1 30 , T2.C2 C2 31 , T2.C3 C3 32 , T2.C4 C4 33 , SUM( 34 CASE 35 WHEN T2.C3 <= T2.MAX_LAG_C4 AND T2.C4 >= T2.MIN_LAG_C3 36 THEN 0 ELSE 1 37 END 38 ) 39 OVER(PARTITION BY T2.C1,T2.C2 ORDER BY T2.C3,T2.C4) GRP_KEY 40 FROM 41 T2 42 ) 43--C1,C2,GRP_KEYごとに集約 44SELECT 45 T3.C1 C1 46, T3.C2 C2 47, MIN(T3.C3) C3 48, MAX(T3.C4) C4 49FROM 50 T3 51GROUP BY 52 T3.C1 53, T3.C2 54, T3.GRP_KEY

投稿2020/05/24 23:42

toyotaku

総合スコア103

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

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

abcmart

2020/05/25 09:45

ありがとうございます! 動作確認し、問題なく抽出できること確認しました。 想定結果の1行目はおっしゃる通り誤りですね。 大変助かりました。 改めまて、感謝致します。
abcmart

2020/05/25 09:47

実際にはストアドプロシージャを使用しておりますが、今回のようにSQL単体でまかなえるのであれば、これはこれでシンプルで問題ないとおもっております。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問