前回の質問
http://q.hatena.ne.jp/1195028480
でテーブル同士のフィールドをチェックし、出力する方法を教えていただきました。
そして
SELECT * FROM b_table AS b LEFT JOIN a_table AS a on (b.money>=a.money_s AND b.money<=a.money_b AND b.tax=a.tax) WHERE b.money is not null ORDER BY a.a_table_id
というようにすると、aテーブル(条件設定)で指定した条件に合ったbテーブル(料金表)のレコードを抽出出来るようになりました。
そこで質問ですが、aテーブルのtaxに値が入っていないレコードは結合条件を
(b.money>=a.money_s AND b.money<=a.money_b)
としたいのですが、そのような事は可能でしょうか?
(つまり、aテーブルに入力されている条件が、2つの場合・3つの場合(レコード毎で異なる場合)でも出力できるようにしたい)
SQL文を分けて2つ書けば出来るでしょうが、あくまで「1つのSQL文で出来る場合」を教えて下さい。もし、不可能ならそれで納得します。
MySQLは4.0.26を使っています。その他のバージョンで上記の事が可能なら教えて下さい。
前回の質問の回答は、LEFT JOINにする必要はなく、INNER JOINでよかったですね。失礼しました。
WHERE b.money is not null
a_tableをLEFT JOINするのだから、a_tableのキー列でないと意味がないですが?
以下のSQLで、前回の期待した結果と同じ結果が得られると思います。
SELECT * FROM b_table AS b INNER JOIN a_table AS a ON (b.money>=a.money_s AND b.money<=a.money_b AND b.tax=a.tax) ORDER BY a.a_table_id
それで今回の要件に関してですが、今回はLEFT JOINを使う方法になります。
以下のSQLでいかがでしょうか?
SELECT * FROM b_table AS b LEFT JOIN a_table AS a ON (b.money>=a.money_s AND b.money<=a.money_b AND b.tax=a.tax) WHERE a.money_s IS NOT NULL AND a.money_b IS NOT NULL ORDER BY a.a_table_id
aテーブルの対象レコードにtaxの値が無い場合
これは、Aのtaxはnullと考えていいでしょうか?
もしそうなら、「or a.tax is null」といった条件を追加する方法が、よく行われると思います。
select * from b_table as b left join a_table as a on b.money>=a.money_s and b.money<=a.money_b and (b.tax=a.tax or a.tax is null) order by a.a_table_id
ありがとうございます。こういうやり方があるんですね。当初の目的としてはうまくできました。
ただ、別質問にした方が良いかもしれないんですが、IFみたいな事って出来ませんかね?
aテーブルに「種類(type)」と言うのを追加して、
typeが1なら結合条件は「b.money>=a.money_s and b.money<=a.money_b and b.tax=a.tax」になる。
typeが2なら「b.money>=a.money_s and b.money<=a.money_b」
のような。
MySQLでIFを使えるのは知っていますが、回答していただいたSQL文に果たしてIFを組み込み、
私が思っているような条件分岐が出来るものだろうか?もし出来たらより汎用性が広がる
と思っています。何度もすみませんが、もしご存じでしたら、教えていただければと思います。
希望の操作ができる検索条件例です。
where b.money>=a.money_s and b.money<=a.money_b and (b.tax=a.tax and type=1 or type=2)
RDBMSは、インデクスの定義と、検索条件、ORDER BYやGROUP BY、DISTINCTといった指定等の
組み合わせから、なるべく最適なアクセス計画を作ろうとします。
そのため、DB操作に直接関係しない検索条件を、SQL中に指定可能だからといって、指定していいか?」
ということも考える必要があります。
今回の場合は、typeを含めると、(money,tax,type)という列構成のインデクスがあり、データ件数が
1000件以上くらいなら、インデクスがない場合に比べ、差が出るかもしれません。
データ件数が多くても1000件程度なら、それ程、気にする必要はないですけどね。
ありがとうございます。非常に参考になりました。
また、コメントの件もさんこうにさせていただきます。
すみません、ちょっと質問の意味と違うような…。
三番目の例は私が質問で出した例の、WHEREの部分に追加していただいて、money_sとmoney_bがNULLでない場合を条件にしていますよね?(ちなみに、b.money is not nullとなっているのは、コピペミスです。すみません)
そうではなくて、例えば
は、bテーブルのtaxとaテーブルのtaxが一致するものを表示するという条件ですが、「aテーブルの対象レコードにtaxの値が無い場合、この部分を避けたい」と言うのが希望です。
money_sとmoney_bしか入力していない場合は「b.money>=a.money_s AND b.money<=a.money_b」という結合条件を、money_sとmoney_bとtaxを入力している場合は「b.money>=a.money_s AND b.money<=a.money_b AND b.tax=a.tax」と言う結合条件を
という、IFみたいな事が出来ないかと思い、相談させて頂きました。
{追記}
ちょっとわかりづらいかもしれませんので、、結果として以下のような出力が出来ればと思っています。
※Bテーブルにはmoney「100」とtax「1」が入っている