データベースの勉強に、かわいいデータベースを実装していたら、だいぶかわいさがなくなってきました。
http://d.hatena.ne.jp/nowokay/20120817#1345197962
ところで、先日、「UNIONの実装はどう?」というコメントに「実際に使わないから乗り気しない」みたいなこと書いたのです。
http://d.hatena.ne.jp/nowokay/20120821#c
実際、SQLでUNIONを使うことは、そこまで多くないと思います。
でも、よく考えると、直接UNIONを使うことはなくても、インデックスが使える条件のORでは、内部的にUNIONが使われることも多いわけです。
ということで、UNION実装してみました。あと、OR演算で面白い結果が出せるように、BETWEENも実装しました。
それと、DISTINCTを実現するために、各タプルにoidをつけるようにしています。
次のようにしてUNIONができます。
System.out.println(Query .from("shohin").between("price", 100, 150) .union(Query .from("shohin").between("price", 250, 300), true));
こんな感じで、「(price between 100 and 150) or (price between 250 and 300)」という条件式での抽出になっています。
|shohin.shohin_id|shohin.shohin_name|shohin.kubun_id|shohin.price| |2|みかん|1|130| |5|わかめ|null|250| |1|りんご|1|300|
unionメソッドの2番目の引数はDISTINCT指定です。
次のように、条件が重なる場合のUNIONでも、DISTINCT指定のおかげで、重複する行は排除されています。ここでは200円の商品であるキャベツが重複するはずです。
System.out.println(Query .from("shohin").between("price", 150, 200) .union(Query .from("shohin").between("price", 200, 250), true));
こんな感じ。
|shohin.shohin_id|shohin.shohin_name|shohin.kubun_id|shohin.price| |6|しいたけ|4|180| |3|キャベツ|2|200| |4|さんま|3|220| |5|わかめ|null|250|
DISTICNT指定をfalseにすると、重複を排除しません。
System.out.println(Query .from("shohin").between("price", 150, 200) .union(Query .from("shohin").between("price", 200, 250), false));
キャベツが2回でてます。
|shohin.shohin_id|shohin.shohin_name|shohin.kubun_id|shohin.price| |6|しいたけ|4|180| |3|キャベツ|2|200| |3|キャベツ|2|200| |4|さんま|3|220| |5|わかめ|null|250|
ただし、DISTINCT指定が有効なのは、テーブルを抽出した場合だけで、JOINした場合には無効です。
あと、いまはoidをSetにつっこんで重複判定をしているのですけど、一旦oidでソートしておいて重複判定するほうがいいかもしれません。
ソースはこちら。
https://gist.github.com/3380142/e65b7a2b6830f20c648e170f80829325e3312c72