- PR -

SQLの優先順位について

1
投稿者投稿内容
ひろ
ベテラン
会議室デビュー日: 2003/12/26
投稿数: 97
投稿日時: 2007-02-26 17:34
いつもここをみて勉強させていただいております。
現在以下の問題で悩んでおります。

以下のSQLの様に,5種のSQLをUNIONにて発行しています。
仕様では,5種のSQLの内,上に位置するSQLの優先度が高く,
複数件該当した場合は,上に位置するSQLの取得データを用いることとなっています。

よって最初に取得するSQL結果を,優先度の高い取得結果としなければならないのですが,
当SQLでは上記考慮が成されていません。

ORDER句を加える事により上記問題は解決できることと思いますが,そうした場合
列を指定しなければならなくなるため,SELECT句に「*」を用いる事ができなくなります。

SELECT句に「*」を用いる形で,且つ優先度の高い取得結果を上位にすることは可能でしょうか。
ご教授お願い致します。

--------------------------------------------------------------------
SELECT
*
FROM
B_TBL
WHERE
JSO_CD = 'A' AND
ADDRESS_1 = '5' AND
ADDRESS_2 = '14' AND
ADDRESS_3 = 'A' AND
BUILD_1 = 'AAAビル' AND
BUILD_2 = '1階' AND
BUILD_3 = '101号'
UNION
SELECT
*
FROM
B_TBL
WHERE
JSO_CD = 'A' AND
ADDRESS_1 = '5' AND
ADDRESS_2 = '14' AND
ADDRESS_3 = 'A' AND
BUILD_1 = 'AAAビル' AND
BUILD_2 = '101号' AND
BUILD_3 = ' '
UNION
SELECT
*
FROM
B_TBL
WHERE
JSO_CD = 'A' AND
ADDRESS_1 = '5' AND
ADDRESS_2 = '14' AND
ADDRESS_3 = 'A' AND
BUILD_1 = 'AAAビル' AND
BUILD_2 = '1階' AND
BUILD_3 = ' '
UNION
SELECT
*
FROM
B_TBL
WHERE
JSO_CD = 'A' AND
ADDRESS_1 = '5' AND
ADDRESS_2 = '14' AND
ADDRESS_3 = 'A' AND
BUILD_1 = 'AAAビル' AND
BUILD_2 = ' ' AND
BUILD_3 = ' '
UNION
SELECT
*
FROM
B_TBL
WHERE
JSO_CD = 'A' AND
ADDRESS_1 = '5' AND
ADDRESS_2 = '14' AND
ADDRESS_3 = 'A' AND
BUILD_1 = ' ' AND
BUILD_2 = ' ' AND
BUILD_3 = ' '
----------------------------------------------

環境
Oracle9i
WinXP
冬寂
ぬし
会議室デビュー日: 2002/09/17
投稿数: 449
投稿日時: 2007-02-26 17:55
基本的に'*'は使わない、という癖を付けた方がいいです。
(テーブル構造とかなにやら変わった時に、1カラム目が・・・とかあり得る為)
で、カラム名を列挙するのが面倒、という事なら、軽くSQLを作るスクリプトを作ってみるとか、ORMツールを使ってみるとか。

まぁ簡単に解決したいだけなら、
select *, '1' from 〜
などとして、'1'のカラムをソート条件に使ってみればいいのでは?
('1'は、上〜下のSQLによって変える)
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2007-02-26 19:07
保証されないけどたぶん大丈夫な方法でよければ、単にUNIONをUNION ALLにすればよいです。

SELECT 1, * FROM ...
UNION ALL
SELECT 2, * FROM ...
UNION ALL
:
ORDER BY 1;

なら完璧ですが、アプリケーションコードのほうが余計な列に対応できないですかね?
New LKH
会議室デビュー日: 2007/02/02
投稿数: 13
投稿日時: 2007-02-26 19:23
出力仕様として1番目のSQL結果,2番目のSQL結果と順番に出すと言う事でしょうか?
今回は重複行が無いようですが union ですと重複行が消されてしまいます。
union all を使った方が良いでしょう。

order by を指定しない限り保障の限りではありませんが
RDBMS によっては union all だと順番に出てくれるかも知れません。

Oracle9i なら union all で良いでしょう。
とんくま
ベテラン
会議室デビュー日: 2005/08/02
投稿数: 56
お住まい・勤務地: 東京
投稿日時: 2007-02-26 20:17
次の例では、いかがですか?
UNION を使う場合に比べて、1回の表(又は索引)の走査で済むので、早くなる可能性が高いと思います。
コード:
SELECT *

FROM (SELECT *
FROM (SELECT *
, CASE
WHEN BUILD_1 = 'AAAビル'
AND BUILD_2 = '1階'
AND BUILD_3 = '101号' THEN
1
WHEN BUILD_1 = 'AAAビル'
AND BUILD_2 = '101号'
AND BUILD_3 = '' THEN
2
WHEN BUILD_1 = 'AAAビル'
AND BUILD_2 = '1階'
AND BUILD_3 = '' THEN
3
WHEN BUILD_1 = 'AAAビル'
AND BUILD_2 = ''
AND BUILD_3 = '' THEN
4
WHEN BUILD_1 = ''
AND BUILD_2 = ''
AND BUILD_3 = '' THEN
5
ELSE NULL
END AS Rank
FROM B_TBL
WHERE
JSO_CD = 'A'
AND ADDRESS_1 = '5'
AND ADDRESS_2 = '14'
AND ADDRESS_3 = 'A'
) AS T
WHERE Rank IS NOT NULL
ORDER BY Rank
) S
ROWNUM = 1;


但し、5組のいずれの条件にも合わない行も中間結果に含まれますので、データの性質や索引のつけ方によっては UNION の方が早くなる場合もあるでしょう。
その場合は、条件を2回書かなければならないわずらわしさはありますが、次のようにすれば良いと思います。
コード:
SELECT *

FROM (SELECT *
FROM (SELECT *
, CASE
WHEN BUILD_1 = 'AAAビル'
AND BUILD_2 = '1階'
AND BUILD_3 = '101号' THEN
1
WHEN BUILD_1 = 'AAAビル'
AND BUILD_2 = '101号'
AND BUILD_3 = '' THEN
2
WHEN BUILD_1 = 'AAAビル'
AND BUILD_2 = '1階'
AND BUILD_3 = '' THEN
3
WHEN BUILD_1 = 'AAAビル'
AND BUILD_2 = ''
AND BUILD_3 = '' THEN
4
WHEN BUILD_1 = ''
AND BUILD_2 = ''
AND BUILD_3 = '' THEN
5
END AS Rank
FROM B_TBL
WHERE
JSO_CD = 'A'
AND ADDRESS_1 = '5'
AND ADDRESS_2 = '14'
AND ADDRESS_3 = 'A'
AND ( BUILD_1 = 'AAAビル'
AND BUILD_2 = '1階'
AND BUILD_3 = '101号'
OR
BUILD_1 = 'AAAビル'
AND BUILD_2 = '101号'
AND BUILD_3 = ''
OR
BUILD_1 = 'AAAビル'
AND BUILD_2 = '1階'
AND BUILD_3 = ''
OR
BUILD_1 = 'AAAビル'
AND BUILD_2 = ''
AND BUILD_3 = ''
OR
BUILD_1 = ''
AND BUILD_2 = ''
AND BUILD_3 = ''
)
) AS T
ORDER BY Rank
) S
ROWNUM = 1;




[ メッセージ編集済み 編集者: とんくま 編集日時 2007-02-26 20:43 ]
ひろ
ベテラン
会議室デビュー日: 2003/12/26
投稿数: 97
投稿日時: 2007-03-02 16:20
ご丁寧に解説ありがとうございます。
とんくまさんの方法で解決する事ができました。
ありがとうございましたm−−m
1

スキルアップ/キャリアアップ(JOB@IT)