特殊なレコードの取得方法

このQ&Aのポイント
  • テーブルから特定の条件に合致するレコードを取得する方法についての質問です。
  • 現在の方法では、インラインビューを複数使用しているため、処理が遅くなっています。
  • インラインビューを1つで済ませる方法について教えてください。
回答を見る
  • ベストアンサー

特殊なレコードの取得方法

下記のようなテーブルがあり、 マスタの方は「*」が入っていれば、デフォルト行のような扱いをしたいのです。 ・テーブルの1のデータはマスタのAと完全マッチしているので、Aの行の値が欲しい。 ・テーブルの2のデータはマスタと完全一致はしないが、列4が「*」なのでBの行の値が欲しい。 ・テーブルの3のデータはマスタと完全一致はしないが、列3と列4が「*」なので、Cの行の値が欲しい。 現在は、マスタを別名で完全一致用(m1)、列4が「*」用(m2)、列3と列4が「*」用(m3)の3つをFrom句に記述し、 Select句にて、m1がNULLなら、m2から取得、m2もNULLならm3から取得するというやり方をとっていますが、 実際の「*」がある組み合わせがたくさんあり、それだけインラインビューを用意すると遅くなっているので、 なんとかインラインビュー1つでなんとかならないものでしょうか? テーブル ┌─┬──┬──┬─┐ │01│AAAA│X001│YY│←1 ├─┼──┼──┼─┤ │01│AAAA│X001│ZZ│←2 ├─┼──┼──┼─┤ │01│AAAA│X002│YY│←3 └─┴──┴──┴─┘ マスタ ┌─┬──┬──┬─┐ │01│AAAA│X001│YY│←A ├─┼──┼──┼─┤ │01│AAAA│X001│* │←B ├─┼──┼──┼─┤ │01│AAAA│* │* │←C └─┴──┴──┴─┘

  • Oracle
  • 回答数3
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

一致する項目の数で、レコードを選択すれば良いと思うので、 select T1,T2,T3,T4,M1,M2,M3,M4 from ( select T.*,Mx.*,row_number() over(partition by T1,T2,T3,T4 order by CNT) R from テーブル T, ( select M1,M2,M3,M4, decode(M1,'*',1,0)+decode(M2,'*',1,0)+decode(M3,'*',1,0)+decode(M4,'*',1,0) as CNT from マスタ M ) Mx where decode(M1,T1,1,'*',1,0)=1 and decode(M2,T2,1,'*',1,0)=1 and decode(M3,T3,1,'*',1,0)=1 and decode(M4,T4,1,'*',1,0)=1 ) where R=1 とか。

kurocky
質問者

お礼

まさにやりたいことができました! 実際に組み込みたいSQLは巨大で複雑なものですが、 試してみたいと思います。 ありがとうございました。

その他の回答 (2)

  • reset_cat
  • ベストアンサー率68% (94/138)
回答No.2

すでに#1のSQLに準ずるものになっているのであれば、キーにインデックスが無いとかはありませんか? 蛇足 インラインビューとは普通以下のようなものを指すを思います。今回のSQLは単に同一テーブルの複数回結合です。マスタにユニークインデックスが適切に作成されていれば、通常マスタが原因で遅くなるとは思えないのですが・・・ select a.*, b.* from ( select * from table1 where key = 1 ) a, table2 b where a.key = b.key

kurocky
質問者

お礼

コメントありがとうございます。 実際、該当するSQLをオブジェクトブラウザ等で実行すると、 100件ほどなのに、15秒ほどかかり、 マスタを複数回結合しているのをやめると、4秒になりました。 マスタにはユニークが設定されていますが、 複数回結合の相手が大きなViewのため、それで遅いのかも知れません。

  • reset_cat
  • ベストアンサー率68% (94/138)
回答No.1

この手の質問は試行したSQLを書かないと、アドバイスが付きにくいと思います。 ざっと考えてこんなSQLでイケるのでわないかと・・・データ部の情報がないので、そのあたりはテキトーです。 select case when マスタ1.データ is not null then マスタ1.データ when マスタ2.データ is not null then マスタ2.データ else マスタ3.データ end as "データ" from テーブル, マスタ マスタ1, マスタ マスタ2, マスタ マスタ3 where マスタ1.列1(+) = テーブル.列1 and マスタ1.列2(+) = テーブル.列2 and マスタ1.列3(+) = テーブル.列3 and マスタ1.列4(+) = テーブル.列4 and マスタ2.列1(+) = テーブル.列1 and マスタ2.列2(+) = テーブル.列2 and マスタ2.列3(+) = テーブル.列3 and マスタ2.列4(+) = '*' and マスタ3.列1(+) = テーブル.列1 and マスタ3.列2(+) = テーブル.列2 and マスタ3.列3(+) = '*' and マスタ3.列4(+) = '*'

kurocky
質問者

お礼

回答ありがとうございます。 >現在は、マスタを別名で完全一致用(m1)、列4が「*」用(m2)、列3と列4が「*」用(m3)の3つをFrom句に記述し、 >Select句にて、m1がNULLなら、m2から取得、m2もNULLならm3から取得するというやり方をとっていますが、 >実際の「*」がある組み合わせがたくさんあり、それだけインラインビューを用意すると遅くなっているので、 >なんとかインラインビュー1つでなんとかならないものでしょうか? 上記で伝えた気になっていました。 わかりにくくて申し訳ありません。 現状はまさしく回答して頂いた通りなのですが、 マスタを別名で何個も宣言しているので、 これが1個にならないか?という質問でした。

関連するQ&A

  • SQLでデータを1件だけ取得したいのですが。

    SQLでデータを1件だけ取得したいのですが。 以下のようなテーブルが2つあるとします。 ------------------------------------ テーブルA     テーブルB   値X           値X    値Y   1           1    20   2           2    NULL   3           2    60   4           2    70               4    NULL               4    NULL ------------------------------------ ここで、テーブルAの値Xと、テーブルBの値Xをリンクさせます。 テーブルAにデータがあれば、テーブルBに無くても出力します(外部結合イメージ) テーブルAの値Xに対して、テーブルBの値Xは2件以上リンクされる可能性があります。 この場合は1件のみ出力します。 その1件の決め方は、テーブルBの値YがNULLでは無く最大の物です。 但し値Yは全てNULLの可能性もあるので、その場合NULLとして1件出力します。 上記の出力イメージ ------------------------------------  値X    値Y  1    20  (1件の場合そのまま出力。1件がNULLでもそのまま出力)  2    70  (NULLではない最大の1件を出力)  3    NULL  (テーブルBになくても出力)  4    NULL  (値が全てNULLの場合、NULLとして1件出力) ------------------------------------ どのようなSQLを記載すれば実現可能でしょうか?

  • 一致する項目の検出?

    こんにちは。 ある値とデータの中から一致したら、その行を取り出すという基本的なところで困っています。 データは 1111,aaaa,gggg 2222,gggg,5555 tttt,hhhh,3333 . . となっています。 例えば、値Xが2番目の値ggggと一致する場合、その行の2222という値を表示する、といった風にするにはどうすればよいでしょうか。 値Xがhhhhならば、ttttを取り出したいです。 splitでデータを一行取り出すのですが、どうしても、最初の一行しか取り出せず、値Xと2番目のggggと一致する場合の行を読み取る、というところがうまくいきません。 わかりにくい説明で申し訳ありませんが、よろしくお願いします。

    • ベストアンサー
    • CGI
  • レコードの一致方法

    テーブルA(マスター) [コード]、[商品名]        ○○○、△△△ テーブルB [コード]、[商品名]       ○○○、△△△ テーブルC [コード]、[商品名]       ×××、△△△ 以上のように、3つのテーブルの不一致クエリーなどを 抽出する場合、テーブルAとB同士の場合は、一致しないのはコードを結合線で結べば、すぐに出てきますが、テーブルAとCの比較の場合は、コードを結合線で結んだところで、違うのでうまくできません。 商品名は△△△なので、コードが違っていても、商品名はあっているので、不一致ではなく、一致しているというように考えたいのです。 △△△についてのコードは×××、○○○というように2つ以上持っているような感じですれば、うまくいくとおもっているのですが、こういう場合はテーブルAにコードのフィールドを2つ作っておいて、結合線でつなぐときに切り替えてするしかないのでしょうか? テーブルA(マスター)で、このような、2つのコードを持っているとおもわれる商品はレコード100以上あって、それをそれぞれ選びながら入力していかないかとおもうと、大変な作業化とおもっているのですが、アドバイスあればお願いします。

  • 同一テーブルのカラムの結合による取得

    列A 列B 列C 111 AAA PPP 222 AAA QQQ 333 AAA null 444 AAA null と言うテーブルがあるとして、 列Cがnullのレコードとnullでないレコードを列Bで ジョインし、下記のような結果を取得したいです。 列A 列C 333 PPP 333 QQQ 444 PPP 444 QQQ 今は SELECT X.列A ,Y.列C FROM table X ,table Y WHERE X.列B = Y.列B AND X.列C IS NULL AND Y.列C IS NOT NULL で取得しています。 この同じテーブルであるtableを二つ使わずに 同様の結果を取得するSQLはありますでしょうか。

  • EXCEL VBA オートフィルタの値コピー2

    たびたびすいませんよろしくお願いします。 EXCEL VBA オートフィルタの値コピーの追加質問です http://okwave.jp/qa4803815.html?ans_count_asc=20 オートフィルタ後、1日当たり行は10~15行あります、そのうちH列からM列まで、ある1行にデータがありますそのデータをH列から順番にSheet1のM20とM28までコピーしたいのです、ただ日によってその列は空欄の時やM列だけの時もありますもあります。さらにN列からP列まで同じようにデータがある時(H列からM列と行が違うときがあり)、上にある行からSheet1のM20とM28に上詰めでコピーしたいのです。 もっと簡単にいいますとH列からP列まである値を上の行からさらにH列から順番に上詰めでSheet1のM20とM28にコピーしたいのです。 なにとぞよろしくお願いします。 Sub データコピー() Range("AB17") = Format(Sheet3.Range("A3").Value, "yy") Range("AE17") = Format(Sheet3.Range("A3").Value, "mm") Range("AH17") = Format(Sheet3.Range("A3").Value, "dd") Range("AK17") = Format(Sheet3.Range("A3").Value, "aaa") Range("D22") = Sheet4.Range("D3").Value Range("D25") = Sheet4.Range("E3").Value Range("H22") = Sheet4.Range("F3").Value Range("D22") = Sheet4.Range("G3").Value Range("L22") = Sheet4.Range("K3").Value Range("Q22") = Sheet4.Range("L3").Value Range("U22") = Sheet4.Range("M3").Value .   .   . End Sub

  • アクセス ADO Null以外のレコードの件数を取得したい

    アクセス ADO Null以外のレコードの件数を取得したい テーブルにレコードが100行あり、そのうちNull値は40行あります。(主キーではないです) この時、ADOでNull以外にフィルタをかけたいのですが For i = 1 To RS.RecordCount RS.Filter = "フィールド = '*'" でも RS.Filter = "フィールド = 'Null''" でも、文字列になってしまい、うまくいきません。 RS.Filter = "フィールド " <> 'Null' だとエラーになります。 「<>null」を抽出する方法をご教授願います。

  • NULLのみを保持した列を除外したレコード取得

    お世話になります。 現在、Visual Basic 6.0 にて 開発をおこなっております。 下記内容で DBからデータを取得し、スプレッドシート(GrapeCity社の製品)に データを表示させる必要があるのですが、 実現方法がよくわからず、非常に困っています。 ・スプレッドシートに取得データを表示する際、 すべての行において データがNULLの列に関しては、 その列自体を表示せず、その次の列を前につめて表示させる まず、上記を実現しようとする場合、 1. データ取得時のSQL文にて、上記内容を満たすようなデータを 取得する 2. 全レコードを取得後、Visual Basic側で構造体に格納した各列の値を 保持した変数の中身をひとつひとつNULLかどうかチェックをする の2つの方法を考えているのですが、1回で条件を満たすようなSQL文が 作成可能なのかどうかも、まだはっきりしていません。 また、上記1、2のどちらがより良い方法なのかも、よくわかりません。 (あるいは、それ以外の方法があれば、それをぜひ知りたいのですが、) どなたか、大変申し訳ないのですが、ご教授願えますか?

  • アルゴリズム(行列積)

    行列M1,M2,M3,M4が以下の数の行、列を持つ行列としたとき、行列積M1,M2,M3,M4をもっとも少ない演算回数で計算するには、どの順序で計算すればよいか? M1:20行60列 M2:60行5列 M3:5行20列 M4:20行100列 全くわかりません(>_<)みなさま手取り足取り教えてくださいm(__)m

  • Excel VBA 2つの条件を満たした行を削除

    Excel2003を使用しています。 CSVファイルを元にデータを作りたく、まずは不要なデータを削除しています。 J列=0の行とJ列=0の行のA列の値と同じ値がA列に入力されている行を削除したく、J列=0のA列の値を一旦別シートに抽出し、その抽出したデータとA列のデータをループして、一致したら削除というコードを書きました。 もし可能であれば、一旦別シートに抽出せずに処理したいのですが、その場合、どのようにコードを書けばいいでしょうか? よろしくお願いします。

  • 不一致クエリでnullまで抽出されてしまいます

    質問です。 現在、accessにて不一致クエリを使用し、テーブルAをチェックし、 マスタテーブルに無い情報が書かれてしまっているフィールドがある場合 抽出して確認をする、というクエリを作りたいと考えています。 不一致クエリにて自動で入る「is null」を使用すると マスタテーブルに無い事が書いてあるレコードは抽出するのですが (逆になぜis nullで相違するレコードが抽出されるのか理解に苦しんでもいるのですが) is nullですので、nullのレコードも抽出されてしまいます。 抽出条件として、マスタテーブルと相違するもの&nullは抽出しない、としたいのですがお知恵を拝借出来ませんでしょうか。 よろしくお願いいたします。