SQLで2つの表を検索して集計する方法

このQ&Aのポイント
  • SQLで2つの表を検索して集計する方法について質問です。
  • PostgreSQLとPHPでサイトを作っている場合、2つの表を結合して集計する方法が知りたいです。
  • 特に、「表1」のid名に応じて、「表2」のid_noの該当件数を取得する方法がわからないので、教えてください。
回答を見る
  • ベストアンサー

SQLで2つの表を検索して集計する場合

PostgreSQLとPHPでサイトを作っています。 下の2つの表がある場合に、「表1」のid名に応じて、 表2のid_noの該当件数を取得したいと思っているのですが、 うまくいかないため質問させいてただきました。 【表1】 id title ----------------------- 1 ほげ1 2 ほげ2 3 ほげ3 4 ほげ4 【表2】 id_no coment ----------------------- 1 コメント 2 コメント 2 コメント 2 コメント 3 コメント 3 コメント 3 コメント 【ほしい結果】 id title count ----------------------- 1 ほげ1 1 2 ほげ2 3 3 ほげ3 3 4 ほげ4 0 SELECT title,id, (SELECT COUNT(*) FROM comment WHERE id_no ='【ID番号】') FROM informations AS count こちらの様なSQL文で取得出来るのではと考えたのですが、 【ID番号】の部分に、「表1」のidを動的に入れる事が出来ずに困っています。 解法がありましたら教えて下さい。

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

  • ベストアンサー
  • don9don9
  • ベストアンサー率47% (299/624)
回答No.2

失礼しました。 COUNT(*)だと表2にレコードが存在しない場合も表1の1件を返してしまうので COUNT(*) → COUNT(表2.id_no) に変えてみて下さい。

xasisi2009
質問者

お礼

続けてのご回答ありがとうございます。 ご指摘の通り変更したところ、目的のとおり表示することができました! ありがとうございました!

その他の回答 (1)

  • don9don9
  • ベストアンサー率47% (299/624)
回答No.1

そういうのは二つのテーブルをJOINして集計するのが一般的な方法だと思います。 SELECT 表1.id, 表1.title, COALESCE(COUNT(*),0) FROM 表1 LEFT JOIN 表2 ON 表1.id = 表2.id_no GROUP BY 表1.id, 表1.title このような感じです。 (実際に動かしていないので、間違っていたらすみません)

xasisi2009
質問者

お礼

ご回答ありがとうございます! JOINして集計するものなのですね。 頂いたコードで実行したところ、ほぼ求めている情報を得ることが出来ました。 只、表2.id_noに該当のIDがない場合も1件としてカウントされてしまったため、 こちらを0件として取ることは出来ますでしょうか。 勉強不足でご迷惑をおかけします。。

関連するQ&A

  • SQLの構文

    以下のように、データの存在と共に名前まで一度に取得 できるクエリの書き方って存在しますか? select count(*), namae from a_class where no='1'; 通常は select count(*) from a_class where no='1'; として、1件ならば、 select namae from a_class where no='1'; で取得しますが。 DBはPostgreSQLです。perlのDBIを利用しています。

  • 複数表での集計値について

    以下のようなテーブル構造。SQLで 集計値を求めたいのですがCNTの値が tableCの件数を取得してしまいます。 (取得したいのはtableA.ID毎のtableB.ID2の件数) 宜しくお願いします。 ・tableA ------------- ID ------------- ・tableB ------------- ID | ID2 ------------- ・tableC ------------- ID2 | TIME ------------- SELECT tableA.ID ,SUM(tableC.TIME) AS TIME ,COUNT(tableB.ID2) AS CNT FROM tableA,tableB,tableC WHERE tableA.ID = tableB.ID AND tableB.ID2 = tableC.ID2 GROUP BY tableA.ID

    • ベストアンサー
    • MySQL
  • 集計のSQLをお教え下さい

    初心者ですよろしくお願いします。 以下の様なテーブルがあり、年月と場所コードで 件数を出したいと考えております。 申し訳ありませんが、SQLの記述をお教え下さい。 年月日 | 場所コード |  20060510   1000 20060511   1000 20060511   2000 20060512   2000 20060601   1000 20060601   2000   ・    ・    ↓ 年月日 | 場所コード | count 200605   1000      2 200605   2000      2 200606   1000      1 200606   2000      1 年月日を年月にして集計したいと考えています。 select 年月日,場所コード,count(*) from table group by substring(年月日 from 1 for 6) ではうまくいきませんでした・・・ よろしくお願いします。

    • ベストアンサー
    • MySQL
  • SQLでグループ化した結果の件数を求めるには?

    下記のようなグループ化した結果を表示するSQL文を作りました。 SELECT メーカコード FROM 部品表 GROUP BY メーカコード, 部品番号 HAVING ((部品番号)="BUHIN1") これを実行するとちゃんと結果が出るのですが、その結果の件数を求めるにはどのようなSQL文を追加すれば宜しいのでしょうか? COUNT文を使うと出来そうなのですが、 SELECT メーカコード, COUNT(メーカコード) AS CNT FROM 部品表 GROUP BY メーカコード, 部品番号 HAVING ((部品番号)="BUHIN1") とやるとメーカコードの個別件数が表示されてしまいます。 どうぞよろしくお願いします。

  • データの件数を集計するための SQL

    データの件数を集計するための SQL について教えてください。 例えば以下のようなテーブルがあります。 ▼テーブル 名前 |交通手段|日付 -----+--------+---- Aさん|バス |5/1 Aさん|バス |5/2 Aさん|バス |5/3 Bさん|バス |5/1 Bさん|電車 |5/2 ※「日付」については、本質問に直接の関係はありません。 このテーブルにクエリを発行して、以下の結果を取得したいと考えています。 ▼取得したい結果 名前 |交通手段|回数 -----+--------+---- Aさん|バス |3 Bさん|バス |1 Bさん|電車 |1 当方がイメージしている流れは以下の通りです。 SQL は苦手でして、これをひとつにまとめることができません。 1) GROUP BY で束ねる SELECT 名前, 交通手段 FROM テーブル GROUP BY 名前, 交通手段 2) 1)の結果の1件目をSELECTする SELECT COUNT(*) FROM テーブル WHERE 名前='Aさん' AND 交通手段='バス' 3) 1)の結果の2件目をSELECTする SELECT COUNT(*) FROM テーブル WHERE 名前='Bさん' AND 交通手段='バス' 4) 1)の結果の3件目をSELECTする SELECT COUNT(*) FROM テーブル WHERE 名前='Bさん' AND 交通手段='電車' なおレンタルサーバ上 (MySQL 5.0.77) で稼働させるため、 なるべく高速な SQL を希望いたします。

    • ベストアンサー
    • MySQL
  • WITH句を使用したSQLの結果

    WITH句を使用して総件数と1~20件までのデータを同時に取得するSQLを組んでみたところ、 WITH TMP AS (SELECT ROW_NUMBER() OVER (ORDER BY NO) AS CHECKROWNUM,NAME FROM TEST_TBL ORDER BY NO) SELECT T1.ALLCNT, T2.* FROM (SELECT COUNT(*) ALLCNT FROM TMP) T1, TMP T2 WHERE T2.CHECKROWNUM BETWEEN 1 AND 20; Oracle10.2.0.3.0のバージョンで ALLCNTが21になってしまう現象が発生してしまいました。 Oracle10.2.0.4.0や9iでは発生せず正しい総件数が取得できるのですが、 バージョンによる不具合は考えられますでしょうか。 それともSQL自体なにか悪い部分があるのでしょうか。 ちなみに T2.CHECKROWNUM BETWEEN 1 AND 100; と帰るとALLCNTが101と帰ってきます。 また、WITH句を使わず下記のようにTMPの部分をWITH句で使用したSQLに 置き換えると正しくALLCNTが取れます。 SELECT T1.ALLCNT, T2.* FROM (SELECT COUNT(*) ALLCNT FROM (SELECT ROW_NUMBER() OVER (ORDER BY NO) AS CHECKROWNUM,NAME FROM TEST_TBL ORDER BY NO)) T1, (SELECT ROW_NUMBER() OVER (ORDER BY NO) AS CHECKROWNUM,NAME FROM TEST_TBL ORDER BY NO) T2 WHERE T2.CHECKROWNUM BETWEEN 1 AND 20;

  • 動的SQLのCOUNTのとり方

    動的SQLで、DBの件数を取得したいのですが、 うまく取得できず困っています。 教えてください! 以下の様に、記述しているのですが取り方間違っていますか? EXEC SQL EXECUTE statment INTO :CNTNUM; PREPEAした、statmentには SELECT COUNT(*) FROM テーブル名 where kbn = 3; と、ごくごく普通のSELECT COUNT文です。 cnt_numは、int型のホスト変数で宣言しています。 デバックしながら実行すると、cnt_numの値は初期化した時の 0のままです。実際取得した件数が0件なのかもと思い 初期化時に3を代入して実行したら、やはり値は3でした。 なので、件数が取得出来ていないようです。 オラクルエラーにもならず、次の処理へ流れていってしまいます。 知っている方、教えてください。

  • SQLで、アクセス集計について困っています。

    アクセス集計について困っています。 mysql> desc access_log; +------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | user_id | varchar(50) | YES | | NULL | | | ip | varchar(15) | YES | | NULL | | | created_at | datetime | NO | | NULL | | | updated_at | datetime | NO | | NULL | | +------------+-------------+------+-----+---------+----------------+ 5 rows in set (0.02 sec) mysql> select * from access_log; +----+---------+-----------+---------------------+---------------------+ | id | user_id | ip | created_at | updated_at | +----+---------+-----------+---------------------+---------------------+ | 1 | admin | 127.0.0.1 | 2010-11-13 21:56:54 | 2010-11-13 23:07:27 | | 2 | admin | 127.0.0.1 | 2010-11-13 21:56:54 | 2010-11-13 23:07:27 | | 3 | admin | 127.0.0.1 | 2010-11-14 21:56:54 | 2010-11-13 23:07:27 | | 4 | admin | 127.0.0.1 | 2010-11-14 21:56:54 | 2010-11-13 23:07:27 | | 5 | admin | 127.0.0.1 | 2010-11-15 21:56:54 | 2010-11-13 23:07:27 | +----+---------+-----------+---------------------+---------------------+ 5 rows in set (0.00 sec) 上記のように定義したテーブルがあります。 SELECT a.id, a.user_id, COUNT(*), DATE(a.created_at) AS date FROM access_log a WHERE (a.user_id = 'admin' AND a.created_at > '2010-11-01 00:00:00' AND a.created_at < '2010-11-29 23:59:59') GROUP BY date ORDER BY a.created_at; のようにして日別のアクセス数の集計をしています。 ここから、同じ日の同一IPのアクセスは1アクセスとして計算したいのですが、 どのようにSQLを書けばよいでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • SQL GROUPで件数の一番多いレコードのみ取る

    SQL GROUPで件数の一番多いレコードのみ取る ORACLE10です。 次のようなテーブルがあります。 USER -----------テーブル名 ID,NAME,DATA----列名 1,A,any 1,A,any 1,B,any 2,C,any 3,D,any このテーブルから、IDをGROUPにして、さらに、一番使用頻度の多いNAMEを取得したいのです。 表示したいのは、IDとNAMEです。 つまり、取得結果例は次のようになります。 取得結果例 ID,NAME----列名 1,A 2,C 3,D SQL文をどのように作れば可能でしょうか? ちなみに、IDやNAMEのマスタテーブルはありません。 自分では、「(select ID, NAME, count(*) from USER group by ID, NAME) COUNT」で、COUNTを内部テーブルにして、グループ内で一番多いcount(*)をmaxで取得してみようかと思ったんですが、そこからアイデアが出ませんでした。

  • SQL WHERE文のノットイコールについて

    初歩的な質問ですみません。 Oracle9iでsqlplusで接続しています。 「member_accountテーブルのdelete_flag(VARCHAR2)カラムの値が'1'ではない」ものを抽出したいと考えてます。 ただ、正しい結果が返ってきません。 何が問題でしょうか?よろしくお願いいたします。 ============================================================ SQL> select count(ID) from member_account; COUNT(ID) ---------- 16450 SQL> SQL> select count(ID) from member_account where delete_flag='1'; COUNT(ID) ---------- 107 SQL> SQL> select count(ID) from member_account where delete_flag<>'1'; COUNT(ID) ---------- 0 SQL> SQL> select count(ID) from member_account where delete_flag!='1'; COUNT(ID) ---------- 0 ============================================================ よろしくお願いいたします。