• ベストアンサー

同じサブクエリが複数出てくるのでまとめたい

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を共通化して一つにまとめる方法はありますでしょうか。

  • MySQL
  • 回答数3
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.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;

ankodaisuki
質問者

お礼

いろいろいじってみましたが、調整後の形は高速化にも繋がってますね。 とても勉強になりました。 ありがとうございました!

その他の回答 (2)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

>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の冗長なデータになりますがほんとにそういう考え方でよいのですか?

ankodaisuki
質問者

補足

問題のソースをできる限り簡素化して具体的な形が見えるようにしてみました。 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)
回答No.1

たぶん共通のサブクエリに対してjoinしていくだけでよいような気がしますが 場合によってはviewやテンポラリテーブルをつかってもよいかもしれません

ankodaisuki
質問者

補足

ありがとうございます。 viewやテンポラリテーブルについてはさっそく試してみました。 joinについてはどういう風にやるのかもう少し詳しくお願いできますでしょうか。 できればクエリは複数でなく一つで済むと助かるのですが。

関連するQ&A

  • サブクエリを利用したSQL文から複数の抽出条件

    例えば、以下のようなサブクエリを利用したSQL文があります。 SELECT table_a.* FROM table_a LEFT JOIN (SELECT table_b.* FROM table_b LEFT JOIN table_c ON (table_b.id = table_c.bid) WHERE table_b.type='1') AS tbl ON (table_a.id = tbl.aid) このSQL文にWHERE句で条件を指定したいのですが、サブクエリで指定しているtblテーブルのvalueフィールドが「1」と「20」のものを抽出したいと思います。 WHERE (tbl.value='1' AND tbl.value='20') としても結果が帰って来ません。 これは、WHEREする条件の数だけ、サブクエリでテーブルを作って条件を指定するのでしょうか? 効率が悪そうなので、他の方法があるのではと思いご質問させて頂きました。 お分かりになる方がいれば、よろしくお願いします。

  • サブクエリの複数項目

    いつもお世話になっております。 サブクエリで複数項目を取得する方法をご教授下さい。 [既存] select 商品, 価格, (select user_id from user_master where user_id = 1 ) from products where 商品ID = 1 上記のようなSQLがあり、 user_masterから取得する項目をもうひとつ追加したいと思っています。(user_name) select 商品, 価格, (select user_id, user_name from user_master where user_id = 1 ) as user from products where 商品ID = 1 と修正したいのですが、当然エラーになってしまいます。 この場合は別にサブクエリを指定して取得した方がいいのでしょうか。 宜しくお願い致します。

  • こんばんは。

    こんばんは。 軽いSQL文がかけずに困っております。 どなたかご教示願います。Postgres8.3になります。 テーブル名 num カラムはuserとidとします。 データは最下部にあるように持ちます。 a~eのユーザのうち、idが2200番台のうち、2201と2202だけをもつユーザを抽出するSQL文を望みます。 a:2200と2203が存在するので偽 b:真 c:2202が無いので偽 d:2203が存在するので偽 e:真 このようなSQLを書きました。 1.numより2201を持つuser 2.numより2202を持つuser 3.numより22~で始まる以外のuser それぞれの等しいuserが真と思ったのですが、本来3.では22~始まるidを持たないuser としなければなりませんでした。 ここで詰まってしまい、タイムアップとなってしまいました。 どのようなSQLが望ましいでしょうか。 よろしくお願いいたします。 select * from num as m, (select x.user from (select user from num where id = 2201 group by user_id) as x, (select user from num where id = 2202 group by user_id) as y, (select user from num where id::text not like '22%' group by user) as z where x.id = y.id and x.id = z.id and y.id = z.id) as n where m.id = n.id; num user,id a,1000 a,1100 a,2000 a,2100 a,2200 a,2201 a,2202 a,2203 a,3000 b,1000 b,2100 b,2201 b,2202 b,3000 b,3100 c,1000 c,2201 c,2203 c,3000 c,3100 c,3200 d,1000 d,2100 d,2201 d,2202 d,2203 d,3000 d,3100 d,3200 e,1000 e,2201 e,2202 e,3000 e,3100 e,3200 e,3300

  • サブクエリを使わずに実現したのですが。。。

    現在、Mysql 4.0xを利用してDBを構築しています。 しかしながら、サブクエリが使えないため以下のようなクエリが実現できず困っております。 EX: select mg.*,sumlg.* from mg left join (select id,uid from lg where uid = '00001') as sumlg on mg.id = sumlg.id where sumlg.id is null; 上記SQLは特定のユーザーIDの、テーブルBに存在しないテーブルAのIDをユーザー単位で切り分け抽出するSQL文です。 (テーブルBにはIDとUIDでユニークになるレコードが格納されています。) 上記を実現するためのSQLをどなたかアドバイスください。 どうぞよろしくお願いします。

    • ベストアンサー
    • MySQL
  • サブクエリについてお教え下さい

    サブクエリについてお教え下さい リレーションの事がしっかりわかっていないでおうかがいします。 下記のようなデータがあります。 T_ANIMALとT_SIZEの間にはリレーションがありません。 テーブル名 T_ANIMAL ID,NAME 001,猫 002,犬 003,猿 テーブル名 T_SIZE SIZE_ID,SIZE A,100 B,200 C,300 下記のSQLを実行しましたが、シンタックスエラーと出ました。 Select ID,NAME, (Select SIZE from T_SIZE where SIZE_ID = 'A') from T_ANIMAL 下記のような出力希望結果を出すのは無理なのでしょうか? 出力希望結果 001,猫,100 002,犬,100 003,猿,100 リレーションが無いテーブルから情報を引っ張ってきて表示したいです。 よろしくお願いいたします。 環境はWin 7 HomeとMYSQL5.0です。

    • ベストアンサー
    • MySQL
  • viewでfrom句にサブクエリが書けない

    こんにちは。MYSQLのVIEWの代替についてお教え下さい。 下記でinner joinについて教えて頂きました。 http://okwave.jp/qa/q7296711.html 環境はWin 7 MYQL5です。 t1テーブルのデータ ID,在庫 001,22 t2テーブルのデータ ID,出庫 001,17 001,3 SELECT A.z AS `在庫`,B.* FROM (SELECT SUM(stock) AS z FROM t1 WHERE id='001' GROUP BY id) A INNER JOIN t2 B ON A.id=B.id というコードで、それぞれのテーブルをグループ化してグループ化したもの同士をJOINしました。 このコードを元にVIEWを作り、そのVIEWを対象にクエリを作ろうと考えていました。 しかしながら、MYSQLのVIEWではFROM句でサブクエリは使えませんでした。 http://www.klab.jp/media/mysql/index4.html 上記のコードを書きなおして、なんとしてもVIEWで利用したいのですが、FROM句でサブクエリを使わずにVIEWを作成する方法がわかりません。 どのようにリライトすればよいか、ご助言お願い致します。

    • ベストアンサー
    • MySQL
  • Nzを使用したサブクエリのLeftJOINのnul

    Access 2016について質問があります。 以下の2つのテーブルがあります テーブル1 ID A B 1 a1 b1 2 a2 b2 3 a3 b3 テーブル2 ID 除外a 除外b 1 a1 (null) 2 (null) b1 テーブル2に対してnullを"*"に変更したサブクエリと テーブル1をLeftJoinで結合するクエリを作成します。 SELECT テーブル1.ID, a, b, Q.除外a, Q.除外b FROM テーブル1 LEFT JOIN (select ID, Nz(テーブル2.除外a,"*") as 除外a,Nz(テーブル2.除外b,"*") as 除外b from テーブル2) AS Q ON テーブル1.ID = Q.ID; 通常、Left Joinで結合する場合、右側のテーブルに存在しないIDは NULLになるはずです。 しかし、サブクエリにNzを使うとなぜか、nullにならず「*」になります。 (ID3の行の除外aと除外bがnullにならずに「*」になる) a b 除外a 除外b a1 b1 a1 * a2 b2 * b1 a3 b3 * * なぜこのようなことが起こるのでしょうか? この現象の回避方法はありますか?

  • Access select句でのサブクエリ

    Access2010でのサブクエリについてお教えください。 注文テーブル 商品コード,数量,フラグ A,3,x B,2,x C,1,x A,3,y B,4,y C,3,y このようなテーブルがあります。 SELECT 商品コード,数量 FROM 注文テーブル GROUP BY 商品コード A,6 B,6 C,4 やりたい事はフラグがxの数量も表示たいと思っています。結果としては、下記の結果が欲しいです。 A,6,3 B,6,2 C,4,1 select句でサブクエリを作りました。 SELECT 商品コード,数量,(SELCT 数量 FROM 注文テーブル WHERE フラグ='x' GROUP BY 商品コード) FROM 注文テーブル GROUP BY 商品コード しかしこのコードを実行すると、「このサブクエリでは1つのレコードしか返せません」と表示されます。 どこを修正したら正しいデータを取得することができるでしょうか?

  • 複数JOINしているとCOUNTが正しく取得できな

    LAMP環境で開発をしています。 SQL文でCOUNTを求める際に、まとめて結果を求めようとして上手く行きません。 状況としては以下です。 テーブルdはidをkeyにa,b,c3つのテーブルとjoinしています。 id = 1の場合、テーブルa,b,cにマッチするレコードがそれぞれに4個、1個、0個あります。 ひとつひとつを SELECT COUNT(CASE WHEN a.name IS null THEN 1 ELSE null END) as a_count FROM d INNER JOIN a ON a.id = d.id WHERE d.id = 1 として結果を求めると4,1,0と出るのですが、まとめて SELECT COUNT(CASE WHEN a.name IS null THEN 1 ELSE null END) as a_count, COUNT(CASE WHEN b.name IS null THEN 1 ELSE null END) as b_count, COUNT(CASE WHEN c.name IS null THEN 1 ELSE null END) as c_count FROM d INNER JOIN a ON a.id = d.id INNER JOIN b ON b.id = d.id INNER JOIN c ON c.id = d.id WHERE d.id = 1 とすると28,5,0という値が返されます。 どのように書けば正しい4,1,0を得られるのでしょうか? よろしくお願いします。

    • ベストアンサー
    • MySQL
  • 横並び表記について

    すみません。。 ACCESSで以下のようなtbテーブルを横に表示たいと思うのですが、 idが飛ぶと歯抜け状態になってしまいます。。 これをidが飛んでも詰める形にするにはどのようにすればよいでしょうか。。 tb id name 1 a 2 b 3 c 4 d 5 e 7 g 実行結果 a.id a.name b.id c.name c.id c.name 1 a 2 b 3 c 4 d 5 e 7 g sql構文 SELECT a.*, b.*, c.* FROM ((SELECT * FROM tb1 WHERE id Mod 3=1) AS a LEFT JOIN (SELECT * FROM tb1 WHERE id Mod 3=2) AS b ON a.id+1=b.id) LEFT JOIN (SELECT * FROM tb1 WHERE id Mod 3=0) AS c ON a.id+2=c.id ORDER BY a.id