0

これが私が持っているものです:

T1 は、複雑な SQL からの ID と合計の大きな選択です。TA、PF、および BL は、異なるアドレス情報を保持するための 3 つの異なるテーブルです。

T1 の各 ID の正しいアドレスを取得するには、次の 3 つの階層ルールに従う必要があります。

TA は、T1.ID を持つ行の存在をチェックする最初のアドレス テーブルです。行が TA に存在する場合、アドレスを取得し、テーブル PF と BL のチェックを無視します。

PF は、T1.ID で TA から何も返されないかどうかを確認する 2 番目のアドレス テーブルです。行が PF に存在する場合、アドレスを取得し、テーブル BL のチェックを無視します。

BL は、PF から T1.ID で何も返されないかどうかを確認する 3 番目のアドレス テーブルです。BL に行が存在する場合は、アドレスを取得します。

現在、次のようなコードがあり、UNIONを使用せずに個別に実行しても長時間実行されます!!! このロジックを効率的に記述するにはどうすればよいですか? 助けてください!

select T1.ID, TA.ADDRESS,T1.TOTALS
from T1, TA
where T1.ID = TA.ID and TA.ADDRESS like "1"

UNION

select T1.ID, PF.ADDRESS,T1.TOTALS
from T1, PF
where T1.ID = PF.ID and PF.ADDRESS like "2"
and not exists(select 1
                from TA
               where TA.ID = T1.ID
                 and TA.ADDRESS like "1")
UNION

select T1.ID, BL.ADDRESS, T1.TOTALS
from T1, BL
where T1.ID = BL.ID and BL.ADDRESS like "3"
and not exists(select 1
                from TA
               where TA.ID = T1.ID
                 and TA.ADDRESS like "1")
and not exists(select 1
                from PF
               where PF.ID = T1.ID
                 and PF.ADDRESS like "2")
4

1 に答える 1

0

まず、 に変更ADDRESS like "1"ADDRESS = "1"ます。この場合、DB エンジンは ADDRESS のインデックスを使用できます (存在する場合)。

第二に、これを行うと取り除くことができますnot exist

select T1.ID, TA.ADDRESS,T1.TOTALS, TA.ADDRESS
from T1, TA
where T1.ID = TA.ID and TA.ADDRESS like "1"

UNION

select T1.ID, PF.ADDRESS,T1.TOTALS, PF.ADDRESS
from T1, PF
where T1.ID = PF.ID and PF.ADDRESS like "2"

UNION

select T1.ID, BL.ADDRESS, T1.TOTALS, BL.ADDRESS
from T1, BL
where T1.ID = BL.ID and BL.ADDRESS like "3"

ORDER BY 4

上記のクエリでわかるようにADDRESS、選択した列のリストに を含め、この列で並べ替えました。not existクエリから削除しました。これは、すべてのアドレスが優先度の高い順に選択されることを意味します。

アプリケーションを使用して最初の行のみを取得し、他の行を無視するか、アプリケーション コードを変更できない場合は、TOP (SQL Server の場合)、LIMIT (MySql の場合) のいずれかを使用する必要があります。 、最初の n 行を取得するための ROW_NUM (Oracle の場合) 手法。使用している RDBMS にタグを付けていないので、自分で調べてください

于 2013-03-22T03:16:08.130 に答える