• ベストアンサー

サブクエリなしで2つのテーブルを集計する方法

テーブルA id|cnt|name 1 2 田中さん 2 5 鈴木さん テーブルB id|cnt|name 1 4 田中さん 2 4 鈴木さん サブクエリを使用せず、上記2つのテーブルを集計し、 下記のように出力できるSQLはありますでしょうか? ■期待する総合ランキング結果 id|cnt|name 2 9 鈴木さん 1 4 田中さん P.S まだまだ、安価なレンタルサーバはMySQLは4.0が多く苦労します・・

  • php4
  • お礼率42% (373/888)
  • MySQL
  • 回答数5
  • ありがとう数3

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

  • ベストアンサー
回答No.4

#3回答者です。 >同一のTemporary Tableを、1つのクエリーで2つ以上結合できないという制約 念のために確認しますが、提示したSQLを、「create temporary table」で作った表に対して実行していませんか? もしそうなら、temporaryでない表で実行してください。 MySQLでは、バージョン5.0でも、「同一の一時表に対しては、自己結合等ができない」という制約があります。 提示したSQLは、4.0系のマニュアルを見た範囲では、明らかにその時点で未サポートの機能は使っていないと思います。 (こちらは、MySQL 5.0で実機確認しています) また、バージョン4.0のunionには、以下の制約があるとのことです。 =====マニュアル引用===== MySQL 4.1.1 より前のバージョンの UNION では、最初の SELECT で使用された値のみに基づいて結果の型と長さが決まる、という制約がありました。 ================= つまり、短い文字データ(今回のname列)が最初に見つかると、それ以降の文字データもその長さで切り捨てられるということです。 これに対応するには、cast関数でchar(n)に変換してしまう方法がありますが、サポートされたのがMySQL 4.0.6だそうです。 もう一点、unionを使って全体をorder byする場合は、「各クエリを括弧で囲む」という制約がありました。この制約は、MySQL 5.0では解除されているようです。 これらを考慮すると、以下のようになります。 【改訂版SQL例】 (select A.id,ifnull(A.cnt,0)+ifnull(B.cnt,0) as cnt,cast(A.name as char(10)) as name from A inner join B on A.id=B.id) union all (select A.id,ifnull(A.cnt,0)+ifnull(B.cnt,0) as cnt,cast(A.name as char(10)) as name from A left join B on A.id=B.id where B.id is null) union all (select B.id,ifnull(A.cnt,0)+ifnull(B.cnt,0) as cnt,cast(B.name as char(10)) as name from B left join A on B.id=A.id where A.id is null) order by cnt desc;

その他の回答 (4)

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

SQL的にはNGですが、単純にテンポラリにテーブルAとBを流しこんで GROUP BY してSUMを得るのが妥当では? CREATE TEMPORARY TABLE `TEMP集計`(`id` INT ,`cnt` INT,`name` VARCHAR(30)); INSERT INTO `TEMP集計` SELECT `id`,`cnt`,`name` FROM `テーブルA`; INSERT INTO `TEMP集計` SELECT `id`,`cnt`,`name` FROM `テーブルB`; SELECT `id`,SUM(`cnt`) AS `cnt`, `name` FROM `TEMP集計` GROUP BY `id`; テーブルAとBを別に管理しているのが問題の原因なので、それを 何とかしない限り効率的なSQLは難しいでしょう

回答No.3

#2回答者です。 以下のSQLでどうでしょうか? 最初のクエリは、両方にあるもの、 2番目は、AにありBにないもの、 最後が、BにありAにないもの を得て、unionで繋げています。 select A.id,ifnull(A.cnt,0)+ifnull(B.cnt,0) as cnt,A.name from A inner join B on A.id=B.id union all select A.id,ifnull(A.cnt,0)+ifnull(B.cnt,0) as cnt,A.name from A left join B on A.id=B.id where B.id is null union all select B.id,ifnull(A.cnt,0)+ifnull(B.cnt,0) as cnt,B.name from B left join A on B.id=A.id where A.id is null order by cnt desc;

php4
質問者

お礼

同一のTemporary Tableを、1つのクエリーで2つ以上結合できないという制約により実現できませんでしたが、SQLって結構なんでもできるんですね。大変勉強になりました。結合に関してきちんと勉強してみたいと思います。ありがとうございました。 http://www.mysql.gr.jp/mysqlml/mysql/msg/9187

回答No.2

#1で補足要求した通りだとすると、こんな感じでしょう。 select A.id,A.cnt+B.cnt as cnt,A.name from A,B where A.id=B.id order by cnt desc;

php4
質問者

お礼

ありがとうございます。補足の通りで私の計算ミスでした。 とりあえず1歩前進できました。 しかし・・また新たな壁にぶち当たりました。。 AにあってBにない。BにあってAにない場合がありました。。 流石にこれを1つのSQLで実行することは無理でしょうか?

回答No.1

テーブルAとテーブルBのcntを、足し算するのですか? 期待する結果の「田中さん」のcnt列は、6の間違い? ランキング表ということは、cnt列で降順ソートするのですか?

関連するQ&A

  • サブクエリについてお教え下さい

    サブクエリについてお教え下さい リレーションの事がしっかりわかっていないでおうかがいします。 下記のようなデータがあります。 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
  • 1回のSQLで集計結果順にソートする方法を教えてください

    PHP4+MySQLです。 やりたいことがあるのですが、いいSQLが考えつきません。 お知恵を拝借できれば幸いです。 以下のようなテーブルがあるとします。 ID|ITEMid|DATE 1| 232|2009-06-14 2| 156|2009-06-14 3| 156|2009-06-14 4| 232|2009-06-14 5| 232|2009-06-14 6| 567|2009-06-14 これを次のように集計したいのです。 (ITEMidの登場回数順にソートして、実際の回数も出す) 232:3 156:2 567:1 サブクエリの使えない環境で、1回のSQLで集計することはできるでしょうか。できる場合実際のSQL文を教えていただければ幸いです。 テンポラリテーブル使えば自分でもできそうな気がするので、できれば使わない想定でお願いします。

    • ベストアンサー
    • MySQL
  • 複数テーブルからのカウント集計

    初めて、投稿させて頂きます。 カルテテーブルに登録されたデータより、スタッフごとにどのサービスを何回対応したかを出力したいのですが、経験が浅く考え込んでいます。 また、日付の制限も指定したいです。 何卒、アドバイスをお願い致します。 MySQL 4.0.24-standardを使用しています。 カルテテーブル(chart_table) --------------------------------------- staff | date | service1 | service2 | service3 | service4 | 1 2007-01-27 1 2 0 0 3 2007-02-07 0 0 3 4 2 2007-03-04 1 0 3 4 スタッフテーブル(staff_table) --------------------------------------- no | id | 1 佐藤 2 鈴木 3 田中 サービステーブル(service_table) --------------------------------------- no | name | 1 サービスA 2 サービスB 3 サービスC 4 サービスD 結果(2007-01 ~ 2007-03) ---------------------------------------       佐藤 | 鈴木 | 田中 | サービスA 1 1 0 サービスB 1 0 0 サービスC 0 1 1 サービスD 0 1 1

    • ベストアンサー
    • MySQL
  • mysql3.23でテンポラリテーブルの使い方

    mysql3.23で、以下のようなテーブルでリスト形式の番号を、対応する他のテーブルのデータにマッチさせて代入する方法を教えてください。 [テーブル1] 'id' | 'type' 1 | 1,2 2 | 1,3,5 3 | 2,4 [テーブル2] 'id' | 'name' 1 | red 2 | blue 3 | yerrow 4 | green 5 | pink [このように出力したい] 'a.id' | 'b.name' 1 | red,blue 2 | red,yerrow,pink 3 | blue,green サブクエリなど使えばできるのだと思いますが、 ずっとmysql3.23なので、今まではプログラム側でループさせて出力していましたが、 今回テンポラリーテーブルに挑戦しようと思ったので、テンポラリーテーブルを使って取得する方法があれば、ぜひやり方を教えてください。 お願いします。

  • 複数テーブルの集計

    お世話になっています。 複数テーブルの集計がわからないので質問させてください。 テーブル3のItem1~4にはテーブル2のItemIDを登録します。 エリア毎の参加人数をcsvデータを出力させたいです。 テーブル3においてテーブル2のItemIDが4つあるので、一人に対して4行必要なのかと思いましたが、テーブルの変更ができません。 テーブルの結合まではできましたがその後ができません。 テーブルの変更ができませんので、結合するためにテーブル2の構造とデータが同じテーブルを他に3つ作成しています。 どうぞよろしくお願いします。 テーブル1 AreaID   AreaName --------------------- 1 北海道 2 東北 3 関東 4 北陸 テーブル2 ItemID ItemName --------------------- 1 自由形50 2 自由形100 3 背泳ぎ50 4 平泳ぎ50 テーブル3 ID AreaID   Name  Item1   Item2  Item3 Item4 --------------------------------------------------------- 1   2    鈴木    2    1    4     3 2   3    佐藤    1    null   3    null 3   1    田中    1    2    null   null 4   2    伊藤    3    null   2    4  5   3    川村    null   2    3    null 「集計結果」       参加人数 自由形50 自由形100 背泳ぎ50 平泳ぎ50 --------------------------------------------------------------- 北海道    1     1     1     0     0  東北     2     1     2     2     2   関東     2     1     1     2     0   北陸     0     0     0     0     0

    • ベストアンサー
    • MySQL
  • SQLのサブクエリについて

    サブクエリについて質問です。MySQLで作成した以下の投稿(post)テーブルとコメント(comment)テーブルがあります。サブクエリを使用し、投稿テーブルのタイトルごとにcomment_dateが2017年04月13日から2017年04月19日の範囲内でコメントが何件あるかを取得するSQLはどのように記述できますか?

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

    現在、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
  • 4つのテーブルを結合して集計したいです。

    mysql&php初心者です。 考えて4日目になりますがどうしても出来ないので宜しくお願いします。 現在使っているのは MYSQL4.1でレンタルサーバーです。 そしてCREATE TEMPORARY・CREATE VIEWは使用できないみたいです。 そしてやりたいことは4つのテーブルを結合して集計したいです。 具体的には テーブル1 ID・会社名の順に 35・テスト会社 テーブル2 ID・受注内容・受注金額 35・テスト受注・100000 テーブル3 ID・経 費 35・200 テーブル4 ID・仕 入 35・200 35・500 の4つです。 で希望の結果は ID・会社名・受注内容・経費・仕入 35・テスト会社・テスト受注・200・700 と出したいのですがどうしても経費の部分が『400』となってしまいます。 無理なことをしようとしているのかも知れませんが宜しくお願いします

    • ベストアンサー
    • MySQL
  • テーブル結合方法について

    MySQL5.1で、Table a ,Table b から、Table cのように取り出したいのですが、 SQLでSELECTする方法がわかりません。 Table b優先だけど、Table aにしかデータがない場合もあるといった感じです。 Table a No  Name 1 加藤 2 佐藤 3 田中 Table b No Name 2 佐藤先輩 4 田辺先輩 Table c No Name 1 加藤 2 佐藤先輩 3 田中 4 田辺先輩 どうか、よろしくお願いします。

    • ベストアンサー
    • MySQL
  • MySQL 可変テーブルの集計方法

    今現在、PHP MySQLにてDB&簡単なCMSを作成中です。 仕入テーブル(id, date_y, date_m, id_cost, price, etc...)と勘定項目テーブル(id_cost, name_cost)をid_costをキーにして連結し、月々の勘定項目ごとの集計画面を作成したいのです。 SELECT 仕入テーブル.date_y, 仕入テーブル.date_m, 仕入テーブル.id_direct_cost, 勘定項目テーブル.name_cost, SUM(仕入テーブル.price) AS sumcost FROM 仕入テーブル NATURAL JOIN 勘定項目テーブル WHERE 仕入テーブル.date_y="'.$y.'" AND 仕入テーブル.date_m="'.$m.'" AND 仕入テーブル.typecost="direct" AND 仕入テーブル.id_direct_cost=勘定項目テーブル.id_cost ※$y, $mは集計画面で選択された年月です。 とすると、月々の合計が抽出され、勘定項目ごとの集計ができません。 当方、半年くらい学校にてPHP MySQLを習ったのですが、まだまだ未熟者のため解決できません。 お力をお貸しいただけますと大変ありがたく存じます。 どうぞよろしくお願い致します。

    • ベストアンサー
    • MySQL