FC2ブログ

リンクサーバーは重い Part2

2つのDB(DB1、DB2)のそれぞれ2つのテーブルをJOINする。

select * from
DB1_TBL1 tb1
inner join
DB1_TBL2 tb2 on tb1.a = tb2.b
inner join
DB2_TBL3 tb3 on tb2.b = tb3.c COLLATE Japanese_CI_AS
inner join
DB2_TBL4 tb4 on tb3.c = tb4.d
where
tb1.e= WWWW
and tb2.f = XXXX
and tb3.g = YYYY
and tb4.ih= ZZZZ


が、場合によっては重くてパフォーマンスに問題が出ることがある。
そういう時、リンクサーバー側のデータ量を減らすことによって、改善する場合がある。

select * from
DB1_TBL1 tb1
inner join
DB1_TBL2 tb2 on tb1.a = tb2.b
inner join
(
select * from
DB2_TBL3 tb3
inner join
DB2_TBL4 tb4 on tb3.c = tb4.d
where
and tb3.g = YYYY
and tb4.h = ZZZZ
) DB2tb on tb2.b = DB2tb.c COLLATE Japanese_CI_AS
where
tb1.e = WWWW
and tb2.f = XXXX


リンクサーバー側をサブクエリ(DB2tb)にして、サブクエリ内で必要なデータだけに条件を絞ってしまうことによってデータ件数を減らすことができる。
むろん、著しく効果がある場合もあれば、ない場合もある。

( )で括られた中の文字だけを取得する

データ音痴が「簡単にできる」と安請け合いして来た難題の尻拭い。
( )で括られた中の文字だけを取得したい。

[COUNTRY_TBL] テーブルの [COUNTRY_NAME] カラムに「America(アメリカ)」とある。
このうち「アメリカ」だけを取得したい場合のSQL。

「America(アメリカ)」だけなら、

select substring(COUNTRY_NAME,9,4) from COUNTRY_TBL


で実現は可能だけれども、それだと先頭からの文字数と取得する文字数を指定しているだけだから、「Canada(カナダ)」だとしたら、「ナダ)」、「New Zealand(ニュージーランド)」なら「and(」になってしまう。これではまったく汎用性がない。

まずは、「(」が何文字目にあるかを取得する必要がある。

select charindex('(',COUNTRY_NAME)) from COUNTRY_TBL


これで取得できる値は「America(アメリカ)」なら「8」。

「(」から前の文字列を取得。

select left(COUNTRY_NAME',charindex( '(',COUNTRY_NAME)) from COUNTRY_TBL


これで取得できるのは「America(」。
この文字列は不要なものなので、「America(アメリカ)」からこれを削除する。

select replace(COUNTRY_NAME,(left (COUNTRY_NAME,charindex('(',COUNTRY_NAME))),'') from COUNTRY_TBL


「アメリカ)」を取得。
ここまでくればもう一歩、「)」をブランクに置換。

select replace(replace(COUNTRY_NAME,(left (COUNTRY_NAME,charindex('(',COUNTRY_NAME))),''),')','') from COUNTRY_TBL


「アメリカ」の取得に成功。

※もし「)」の後ろにも文字が入っているデータなら、「(」の処理と同じようなことを「)」でもしなければならない。
※括弧に半角、全角が混じっている場合、replaceしてどちらかに揃える必要がある。半角と全角で同じ処理をしても同じ結果は得られるけれども、複雑過ぎるからおススメできない。
※テーブル・カラムは実在のものではないので、記載したSQL自体は実際に流したものではない。流してエラーが出るようなら、括弧の数が合っていない可能性が高い。