知識不足ですみませんが、
以下の場合の◎の内容が出力できるSQL文を教えてください。
同一のコードが複数あり、有効日時が異なる場合、更新日時に近いレコードを取得したいです。
テーブルの例を記述します。
---------------------------------------
tableA
---------------------------------------
コード | 名称 | 開始日時 | 終了日時
A01 | あ | 2012-04-01 |2014-03-01
A01 | 亜 | 2015-04-01 |2018-03-01
A02 | い | 2012-04-01 |2014-03-01
A02 | 位 | 2015-04-01 |2018-03-01
---------------------------------------
---------------------------------------
tableB
---------------------------------------
コード | 名称 | 開始日時 | 終了日時
B01 | う | 2012-04-01 |2014-03-01
B01 | 宇 | 2015-04-01 |2018-03-01
B02 | え | 2012-04-01 |2014-03-01
B02 | 絵 | 2015-04-01 |2018-03-01
---------------------------------------
---------------------------------------
tableC
---------------------------------------
Aコード | Bコード | 更新日時
A01 | B01 |2012-04-01
A02 | B02 |2013-04-01
A01 | B01 |2014-04-01
A02 | B02 |2015-04-01
---------------------------------------
---------------------------------------
◎SQLで出力したい内容◎
---------------------------------------
Aコード | A名称 | Bコード | B名称 | 更新日時
A01 | あ | B01 | う | 2013-04-01
A02 | い | B02 | え | 2014-04-01
A01 | 亜 | B01 | 宇 | 2015-04-01
A02 | 位 | B02 | 絵 | 2016-04-01
---------------------------------------
※DBはoracleです。プログラムに実装ではないので、sql文が知りたいです。
よろしくお願い致します。
A 回答 (4件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
めんどくさい検索条件が必要ならば SQL を使わないほうが良いです。
複雑怪奇な SQL は極端な性能劣化とかデッドロック発生とか保守性とか...
というわけで
テーブルを正規化して条件を簡単にしましょう
または
PL/SQL を書きましょう
No.3
- 回答日時:
No.2 お礼への回答
> 日時比較に不等号ではなくbetweenを使う理由
たいした理由であはありませんが、between の方が性能が良いとされています。
実際の業務においては「A以上B未満」のケースもあるので、
全てに場合で使えるわけではありませんが。
あとは個人的に、こちらの方が読みやすいので。
> 結合にinner joinを使う理由を是非教えていただけますか。
C に対応する A,B が「必ず一つ」存在する前提で書いたので内部結合にしましたが、
必ず、でなければ以下のどちらかを選んでください。
* 内部結合 inner join で、問題の有るレコードを除外して出力
* 外部結合 left outer join で、問題の有るレコードでも穴あきで出力
あと、
> 他案③結合しない場合
それは内部結合を WHERE 句で書くやりかたです。
SQLが大規模化したときに、検索条件と結合条件がごっちゃになって
読みづらくなるのでオススメしません。
Oracle8 の頃は SQL92 標準の JOIN 句が使えなかったり、
Oracle9 で使えるようになっても性能的に問題があったりと、
いろいろあって昔は結合を WHERE 句で書く習慣がありましたが、
現在はオラクル社の奨励でも JOIN 句となっています。
ご回答ありがとうございます。
between の方が性能良いのですね。結合の仕方についても勉強になりました。
>実際の業務においては「A以上B未満」のケースもあるので
すみません。仕様を五月雨にお伝えしてしまい申し訳ないのですが、
C.upd_dt between A.from_dt and A.to_dtに当てはまらないケースもあります。
そのケースに対応すべく、以下の条件を加えたいです。
現在有効なデータ(C.upd_dt between A.from_dt and A.to_dt)がなければ、
① C.upd_dt < A.from_dt(更新日時より未来のデータ)の名称を表示、①がなければ、
② C.upd_dt > A.to_dt(更新日時より過去のデータ)の名称を表示させる。
「なければ」という優先度をつけたSQLの問合せ方法はあるのでしょうか。
No.2
- 回答日時:
同一コードにおいて有効期間をかぶらないように登録する前提、
ならば以下でよいかと。
前提が崩れると途端に変な結果となりますのでご注意ください。
select A.code, A.name, B.code, B.name, C.upd_dt
from C
inner join A on A.code = C.codeA and C.upd_dt between A.from_dt and A.to_dt
inner join B on B.code = C.codeB and C.upd_dt between B.from_dt and B.to_dt
ちなみに、出力したい内容の
A02 | い | B02 | え | 2014-04-01
については、該当する有効期間が見つからないので、
条件に日付計算をする必要があるかもしれません
回答ありがとうございます。遅くなりすみません。
出力したい内容通りに動かすことができました。
しかし、以下の他案①~③でも同じ結果を得られました。(データのバリエーションは試してないですが)
日時比較に不等号ではなくbetweenを使う理由と、結合にinner joinを使う理由を是非教えていただけますか。
他案①日時の比較をbettweenから不等号とした場合
他案②inner join からleft outer joinを使う場合
他案③結合しない場合
SELECT A.code,A.name,B.code,B.name,C.upd_dt FROM C,A,B
WHERE A.code=C.codeA AND B.code=C.codeB
AND (以下省略。日時の比較はbetweenでも不等号でも出力できました。)
No.1
- 回答日時:
select ... from C
inner join A on A.code = C.codeA and ...
inner join B on B.code = C.codeB and ...
になると思いますが、
質問では以下が不明確ですので、これ以上は書けません
* 更新日時に近いレコード、の判断方法
* C.更新日時 → 出力したい内容.更新日時、の変換方法
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(データベース) 更新クエリをリンクデータベーステーブルに実行し実行時エラー3362固有インデックスに重複する値が含ま 1 2022/09/21 11:44
- Visual Basic(VBA) ExcelのVBAコードについて教えてください。 1 2023/08/09 10:33
- MySQL SQLです。こんな感じですか?あってますか? うまくいきません教えてくださいお願いします 1 2023/07/08 15:27
- Visual Basic(VBA) エクセルのマクロコードの一部分を変更する方法について教えてください。 2 2023/02/17 08:40
- Excel(エクセル) エクセルVBA、間違っているコード内容を正して頂けませんか? エクセルワークシートに納品書を作ったの 2 2023/08/02 21:13
- Visual Basic(VBA) ExcelのVBAコードについて教えてください。 2 2023/05/23 16:28
- MySQL うまくいきません教えてくださいお願いしますSQLです。クエリ構文です。 1 2023/07/07 12:39
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
- Visual Basic(VBA) Excel VBA マクロ ホルダー内にある複数のファイルを規則に従い格納をしたいです 4 2022/11/19 10:58
- その他(プログラミング・Web制作) python 気象データの取得 2 2023/06/20 23:54
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
SQLです。こんな感じですか?あ...
-
グループごとの最高得点者一覧...
-
SQL Server management studio ...
-
update文で改行を入れる
-
Accessでデータシートに同じデ...
-
SELECT 文の NULL列は?
-
ROWNUMでUPDATEをしたいのです...
-
他のデータベースとのテーブル結合
-
テーブル名をカラムとして取得...
-
アクセス レコードセットを更...
-
SQL、2つのテーブルで条件一致...
-
sqlplusで表示が変なので、出力...
-
Accessのテーブルデータを一気...
-
テーブルリンク リンク元を知...
-
SQL 複数テーブルのupdate
-
飲み会で、座敷orテーブルどち...
-
L2SWはARPテーブルを持っている?
-
SQL*LoaderでCSVから指定した列...
-
SQLにて指定日付より前、かつ最...
-
外部キーだけのテーブル(主キ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
このSQLあってますか?教えてく...
-
SQLで漢字名称を都道府県や市区...
-
下記の問合せを行うクエリを、P...
-
SELECT文内での条件分岐
-
下記の問合せを行うクエリを、P...
-
SQLです。こんな感じですか?あ...
-
条件付データ差分の抽出で
-
SQL 主キーによる自動的な表の結合
-
update文におけるwhereとjoinの...
-
グループごとの最高得点者一覧...
-
降順で並び替えて昇順で受け取...
-
SQLの作成方法
-
うまくいきません教えてくださ...
-
サブクエリを使用せずにLEFT JO...
-
現在庫算出方法についてお教え...
-
ACCESS2010 SQL 結合キーにつ...
-
UPDATEでSETする値
-
複数テーブルの結合結果を自分...
-
SQL CASE文に制御について
-
3つの表の外部結合
おすすめ情報
回答ありがとうございます。
* 更新日時に近いレコード、の判断方法
→実は判断方法から悩ましいのですが、同一コードにおいて有効期間をかぶらないように登録する前提のため、
・更新日時より終了日時が大きい(=有効なデータである)
・かつ、終了日時が小さい(=直近)
と判断しようと考えていました。
なので、MIN(終了日時)で 更新日時<終了日時を条件にし
AやBtblから名称を取得できればいいなと考えましたが、
どうにも意図した出力ができません。
* C.更新日時 → 出力したい内容.更新日時、の変換方法
→すみません、イメージが間違ってました。
C.更新日時と出力したい内容.更新日時は同一データの予定です。
(変換の予定はなく、そのまま出力する形です。)
Cの更新日時は、間違っており、Cの更新日時を、出力したい内容の更新日時に読み替えていただけますでしょうか。よろしくお願いいたします。