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

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

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

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

SQL

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

Q&A

解決済

1回答

1845閲覧

下記ロジックを満たすSQL(SELECT)を教えていただけますでしょうか

tokyocats

総合スコア21

Oracle

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

SQL

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

0グッド

1クリップ

投稿2015/06/19 05:20

編集2015/06/22 11:01

下記ロジックを満たすSQL(SELECT)を教えていただけますでしょうか。
データベースタイプはオラクルとなっております。

今入力値として、入力1:SY番号 , 入力2 : 出力数
があるものとします。

ここでは説明のため、仮にSY番号が"sy1" 出力数が"1"とします。

ロジック1:テーブルAから入力1にヒットするSE番号を取得
(例:se1取得)

【テーブルA】
SY番号、SE番号
sy1 、se1
sy2 、se2
sy3 、se3

ロジック2:テーブルBからロジック1で取得したSE番号に対応したZU番号を取得
(例:zu1取得)

【テーブルB】
SE番号、ZU番号
se1 、zu1
se2 、zu1
se3 、zu1
se4 、zu2
se5 、zu2
se6 、zu2

ロジック3:テーブルCからロジック1で取得したSE番号に対応した最大DT(大きいほうのレコード値)を取得
(例:1/3 10:10:12)

【テーブルC】
ID 、SE番号、DT
1101 、 se3 、1/1 10:10:10
1102 、 se3 、1/1 10:10:10
1201 、 se2 、1/2 10:10:11
1202 、 se2 、1/2 10:10:11
1301 、 se1 、1/3 10:10:12
1302 、 se1 、1/3 10:10:12
1401 、 se5 、1/4 10:10:13
1402 、 se5 、1/4 10:10:13
1501 、 se4 、1/5 10:10:14
1502 、 se4 、1/5 10:10:14
1601 、 se6 、1/6 10:10:15
1602 、 se6 、1/6 10:10:15

ロジック4:テーブルBからロジック2で取得したZU番号に対応した全SE番号を取得
(例:se1,se2,se3を取得)

【テーブルB】
SE番号、ZU番号
se1 、zu1
se2 、zu1
se3 、zu1
se4 、zu2
se5 、zu2
se6 、zu2

ロジック5:テーブルCからロジック4で取得した各SE番号に対応した最大DT(大きいほうのレコード値)を取得
(例:1/1 10:10:10,1/2 10:10:11,1/3 10:10:12を取得)

【テーブルC】
ID 、SE番号、DT
1101 、 se3 、1/1 10:10:10
1102 、 se3 、1/1 10:10:10
1201 、 se2 、1/2 10:10:11
1202 、 se2 、1/2 10:10:11
1301 、 se1 、1/3 10:10:12
1302 、 se1 、1/3 10:10:12
1401 、 se5 、1/4 10:10:13
1402 、 se5 、1/4 10:10:13
1501 、 se4 、1/5 10:10:14
1502 、 se4 、1/5 10:10:14
1601 、 se6 、1/6 10:10:15
1602 、 se6 、1/6 10:10:15

ロジック6:ロジック5で取得した各DTをロジック3で取得したDTを基準にしてそれよりも
前の日時の各DTを取得する。
(例:1/1 10:10:10,1/2 10:10:11取得)

ロジック7:ロジック6で取得した各DTを昇順でソートする。
(例:1/1 10:10:10,1/2 10:10:11)

ロジック8:ロジック7でソートした各DTの中から、ロジック3で取得したDTから近い順に
見て、入力2の出力数の数だけ選択及び取得する
(例:1/2 10:10:11を取得)

ロジック9:ロジック8で取得した各DTに紐付いたSE番号をテーブルCより取得
(例:SE2を取得)

かなり細かく段階を分けてロジックを書いておりますが、効率よくまとめてSQLを記述するとなると、おそらくですがどこかのロジックは短縮又は不要になったりするかとおもいます。

その辺りを含めまして最も効率よく一度のSQL文だけでSELECTできるSELECT文を記述して教えていただけますでしょうか。

おそらくサブクエリを使用すると思いますが、サブクエリ数も最低限の数だけ使用するなど工夫をいただけると幸いです。

以上、宜しくお願い致します。

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

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

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

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

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

guest

回答1

0

ベストアンサー

とりあえずこんな感じで

lang

1SELECT 2 dat.se_num 3FROM( 4 SELECT 5 , D.se_num 6 , B.zu_num 7 -- 基準より前の人で基準に近い順だから古い方からナンバリング 8 , ROW_NUMBER() OVER(ORDER BY E.dt DESC) ord 9 FROM B 10 -- 指定されたSEのZUを求める 11 JOIN A 12 ON A.se_num = B.se_num 13 AND A.se_num = [sy1] 14 -- 指定されたSEのDTを求める 15 JOIN C 16 ON A.se_num = C.se_num 17 -- 同じZUのSEを求める 18 JOIN B AS D 19 ON D.zu_num = B.zu_num 20 -- 同じZUのSEで基準のDTより前のDTを求める 21 JOIN C AS E 22 ON D.se_num = E.se_num 23 AND C.dt > E.dt 24) dat 25-- ナンバリングされた値が指定された値より小さいものを取得 26WHERE dat.ord <= [1] 27-- 日付が新しい順になっているので古い順からがよかったらナンバリングの逆順 28ORDER BY dat.ord DESC 29

確認はしていないけどいけるはず
同じ部署の先輩を近い順に指定人数分出したいとかそんな感じですか?

投稿2015/06/19 06:06

kutsulog

総合スコア985

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

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

tokyocats

2015/06/21 23:31

有難う御座います。 これから検証して問題がなければベストアンサーとさせていただきます。
tokyocats

2015/06/22 10:50

kutsulog様 私の認識不足がありまして、テーブルCの情報に誤りがありました。 ID列が不足しておりました。 このため同じSE番号が複数行あります。 従いまして、ロジック3とロジック5において、DTを取得するときに 各SE番号で最大のDTを取得するという条件が加わります。 大変申し訳ありませんが、上記内容を含めて最終形のSQLを記述いただけますでしょうか? 【テーブルC】 ID 、SE番号、DT 1101 、 se3 、1/1 10:10:10 1102 、 se3 、1/1 10:10:12 1201 、 se2 、1/2 10:10:11 1202 、 se2 、1/2 10:10:12 1301 、 se1 、1/3 10:10:12 1302 、 se1 、1/3 10:10:13 1401 、 se5 、1/4 10:10:13 1402 、 se5 、1/4 10:10:14 1501 、 se4 、1/5 10:10:14 1502 、 se4 、1/5 10:10:15 1601 、 se6 、1/6 10:10:15 1602 、 se6 、1/6 10:10:16
kutsulog

2015/06/22 13:12

それではこれでいかがでしょう? -- IDごとに最大のDTを求めるCTE WITH C2(se_num, DT) AS ( SELECT se_num , MAX(DT) DT FROM C GROUP BY se_num ) SELECT dat.se_num FROM( SELECT , D.se_num , B.zu_num -- 基準より前の人で基準に近い順だから古い方からナンバリング , ROW_NUMBER() OVER(ORDER BY E.dt DESC) ord FROM B -- 指定されたSEのZUを求める JOIN A ON A.se_num = B.se_num AND A.se_num = [sy1] -- 指定されたSEのDTを求める JOIN C2 ON A.se_num = C2.se_num -- 同じZUのSEを求める JOIN B AS D ON D.zu_num = B.zu_num -- 同じZUのSEで基準のDTより前のDTを求める JOIN C2 AS E ON D.se_num = E.se_num AND C2.dt > E.dt ) dat -- ナンバリングされた値が指定された値より小さいものを取得 WHERE dat.ord <= [1] -- 日付が新しい順になっているので古い順からがよかったらナンバリングの逆順 ORDER BY dat.ord DESC すべて聞くのではなく、 少しは考えてみて分からないところを聞いた方が実になりますよ?
tokyocats

2015/06/23 12:06

kutsulogs様 ご回答ありがとうございます。 おっしゃるとおり多少考えてわからなければ聞きたい所なのですが、 納期が迫っておりまして、時間が取れずにいます。 但し、いただいた回答の中で、初めて触れること(join,row_number,with等) はそれらをインターネットで調べて理解しながら使用するようにしております。 また、大変申し訳ないのですが、これらのSQLは続きがありまして、得られた SELECT結果を繰り返し実行する処理がございます。こちらに関してもご教授 いただきたいので、是非別に建てる質問へのご回答もどうぞ宜しくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問