- ベストアンサー
同じサブクエリが複数出てくるのでまとめたい
SELECT a.num b.num FROM サブクエリA(いろんな処理 WHERE a_id=ANY(サブクエリC(いろんな処理)) ) AS a, サブクエリB(いろいろ処理 WHERE b_id=ANY(サブクエリD(いろんな処理)) ) AS b このような処理をしているのですが、サブクエリCとサブクエリDは一字一句違わない全く同じ処理をしています。 2回全く同じ処理をするのは処理コストが無駄にかかりますし、同じ内容を示す表記が2度出てくるのは保守性も悪くします。 サブクエリCとDを共通化して一つにまとめる方法はありますでしょうか。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
これって合計じゃなくて単にcount処理をフラグやグレードを指定して取っているだけですね。 //準備 create table A (id int,flag tinyint); create table B (id int,grade tinyint); create table C (id int,val int); insert into A values(1,0),(2,1),(3,0),(4,1),(5,1),(6,0),(7,0); insert into B values(1,0),(2,0),(3,2),(4,2),(5,0),(6,0),(7,0); insert into C values(1,10),(2,20),(3,30),(4,40),(5,50),(6,60),(7,70); //非効率SQL SELECT num_a, num_b FROM (SELECT SUM(IF(flag=0, 1, 0)) AS num_a FROM A WHERE id=ANY(SELECT id FROM C WHERE val<=50)) AS sub_a, (SELECT SUM(IF(grade=2, 1, 0)) AS num_b FROM B WHERE id=ANY(SELECT id FROM C WHERE val<=50)) AS sub_b //調整後 SELECT count(flag) as num_a,count(grade) as num_b FROM C LEFT JOIN A on C.id=A.id and flag=0 LEFT JOIN B on C.id=B.id and grade=2 WHERE val<=50;
その他の回答 (2)
- yambejp
- ベストアンサー率51% (3827/7415)
>joinについてはどういう風にやるのかもう少し詳しくお願いできますでしょうか。 うーん、元のSQLが微妙なのでなんとも言えません 見た感じサブクエリC(D)によりAとBを抽出して結合し列記するという命題であれば たとえばサブクエリAで得られるnumが(1,2)サブクエリBで得られるnumが(1,3)だと このクエリで抽出されるデータは num_a num_b 1 1 2 1 1 3 2 3 のようにA×Bの冗長なデータになりますがほんとにそういう考え方でよいのですか?
補足
問題のソースをできる限り簡素化して具体的な形が見えるようにしてみました。 SELECT a.totalNum, b.totalNum FROM (SELECT SUM(IF(flag=0, 1, 0)) AS totalNum FROM x WHERE id=ANY(SELECT id FROM zzz WHERE 条件)) AS a, (SELECT SUM(IF(grade=2, 1, 0)) AS totalNum FROM y WHERE id=ANY(SELECT id FROM zzz WHERE 条件)) AS b 比較するために二つの合計数(a.totalNum、b.totalNum)を得るものです。 ANYの中身はどちらも完全に同じクエリです。 いかがでしょうか。
- yambejp
- ベストアンサー率51% (3827/7415)
たぶん共通のサブクエリに対してjoinしていくだけでよいような気がしますが 場合によってはviewやテンポラリテーブルをつかってもよいかもしれません
補足
ありがとうございます。 viewやテンポラリテーブルについてはさっそく試してみました。 joinについてはどういう風にやるのかもう少し詳しくお願いできますでしょうか。 できればクエリは複数でなく一つで済むと助かるのですが。
お礼
いろいろいじってみましたが、調整後の形は高速化にも繋がってますね。 とても勉強になりました。 ありがとうございました!