- PR -

10万件のデータでmin()関数を使ったときに実行されない

投稿者投稿内容
有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2009-03-05 12:42
引用:

すいません、ヒントじゃなくなってしまうんですが


いや、ぜんぜん構わないです。むしろ有り難い。格好つけて「ヒントをくれ」なんて言ってすいませんでした(汗。本当に助かります。

一応いただいたSQLを自分なりに解釈してみたのですが、間違っていないでしょうか?
・Aは room と room_cost を結合したもの。仮に room 内に house_rent が含まれていれば A などせず room をそのまま使えば良い
・Bは各propertyにおける最小のhouse_rentのリスト

あと、実際の処理では以下のような流れになっているんです。この流れに対していただいたSQL(以下、G-SQLと略)をそのまま適用したらダメですよね…?
1. ユーザーが入力した条件により絞り込み(例えば house_rent >= 50000 とか、普通ないと思うけど)
2. その「絞り込んだ結果」から各propertyの最も安いroomを取得

これってもし以下のようなテーブルだと動かないと思うんです(面倒だから全部つなげて書きます)
---------------------------------------
room_id, property_id, house_rent
1, 1, 20000
2, 1, 50000
3, 1, 75000
---------------------------------------

絞り込んだ結果をCとします。G-SQLのAの部分はCと入れ替わると思うので

---C(A)-------------------------------------------------
select property_id, room_id, house_rent
from room_cost, room
where room.id=room_id and house_rent >= 50000
--------------------------------------------------------
---Result of C(A)---------------------------------------
room_id, property_id, house_rent
2, 1, 50000
3, 1, 75000
--------------------------------------------------------

っとなって、G-SQLのB部分は
---Result of B------------------------------------------
room_id, property_id, house_rent
1, 1, 20000
--------------------------------------------------------

これを inner join したら結果が0ってなると思います。BにもCが摘要できればいいんですが、それって言うのはこういう感じでOKでしょうか?考え方・構文等間違っているところがあれば教えていただけると助かります(ちなみに sqlite3 では動き、結果も予想通りのように見えた)

※ group by property_id は各propertyからどれでもいいから最安のroomを一つだけ得るために加えてあります。distinctで出来ればいいのですがhttp://d.hatena.ne.jp/justforfun/20080414/1208141971に書いてある方法だとsqlite3ではエラーが発生してしまいました。

コード:
select A.property_id, A.room_id, A.house_rent from 
     ( select property_id, room_id, house_rent
	from room_cost, room
	where room.id=room_id and house_rent >= 50000 ) A
     inner join 
     ( select property_id, min(house_rent) minprice
           from (select property_id, room_id, house_rent
			from room_cost, room
			where room.id=room_id and house_rent >= 50000) C
           where c.room_id=room_id  group by property_id) B
     on A.property_id = B.property_id and A.house_rent = B.minprice
     group by A.property_id;



加えた部分・変更した部分は太字にしてあります。
デューン
大ベテラン
会議室デビュー日: 2004/04/21
投稿数: 174
お住まい・勤務地: Tokyo
投稿日時: 2009-03-05 13:01
AとBのロジック上の解釈はその通りですが、
この二つの意味というか役割を考えてみてください。


シンプルにいけば以下でとれると思うんですがだめですか?。
(実験してませんが、そういうつもりで作ったので)
コード:
select A.property_id, A.room_id, A.house_rent from 
     ( select property_id, room_id, house_rent
           from room_cost ,room
           where room.id =room_id ) A
     inner join 
     ( select property_id, min(house_rent) minprice
           from room_cost ,room
           where room.id=room_id and house_rent >= 50000
           group by property_id) B
     on A.property_id = B.property_id and A.house_rent = B.minprice



有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2009-03-05 13:34
なるほど、役割としては
・A: 必要なColumnを取得するためのテーブル
・B: 絞り込み条件用のテーブル
ということですね(よね?)

先のようなコードを書いたのは既に絞り込みを行ったテーブルが存在していたからです。そのテーブルをCとすれば以下のような感じですかね?
※ ORMを利用しているため完全なシンプルSQLはかけないのでこの様な回りくどい書き方をします。

コード:
C: <example>
select * from room where room.floor >= 10 outer join station where room.id = station.room_id and station.timetaken <= 10
 - 十階以上に存在する部屋で駅が徒歩10分いないの部屋テーブル(本当はstationはMany to Manyだけど面倒いのでOne to Manyと仮定して)
C: <example2>
select * from room where room.arrangement == 2DK outer join branch where room.id = branch.room_id and branch.name in ('東京支店', '京都支店')
 - 間取りが2DKで取扱い支店が'東京支店'か'京都支店'のテーブル

select A.property_id, A.room_id, A.house_rent from 
     ( select property_id, room_id, house_rent
           from room_cost ,room
           where room.id =room_id ) A
     inner join 
     ( select property_id, min(house_rent) minprice
           from C
           where room.id=room_id
           group by property_id) B
     on A.property_id = B.property_id and A.house_rent = B.minprice



こういう書き方ならCがどんなテーブルでOKですよね?(property_idとhouse_rentが存在していれば
デューン
大ベテラン
会議室デビュー日: 2004/04/21
投稿数: 174
お住まい・勤務地: Tokyo
投稿日時: 2009-03-05 14:07
B側の where room.id=room_id は結合条件ですので、なくていいと思いますが
たぶんそれでうまくいくと思います。
有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2009-03-05 23:46
>デューン様
一番最初に提示したデータを再び作成し実験して見たところ無事に動作しました。

無知な僕に色々とご親切に教えていただいて有難うございました^^

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