アプリ版:「スタンプのみでお礼する」機能のリリースについて

3つのテーブルを結合(INNDR JOIN)している状態で重複するデータを無くしたいです。

[テーブルの種類とカラム内容]
posts(id,name)
categories_posts(id,post_id,category_id)
categories(id,name)

[現在作成しているSQL文]
SELECT * FROM categories_posts
INNER JOIN potsts ON categories_posts.post_id = posts.id
INNER JOIN categories ON categories_posts.category_id = categories.id;


1つのpostsに複数のcategoryが登録されている場合、postsのデータが重複して取り出されるので、重複するpostsを1つにまとめたい。

GROUP BY を使うというのはいろいろと調べてみてわかりました。自分で実験してみましたが、エラーになってしまいます。

1.postsとcategoriesの関連をcategories_postsというテーブルで管理しています。これらのテーブルをつなげるには上記に記載したSQL文で良いか?(データは取得できていますが記載するテーブルの順番など、これで良いのか?)

2.GROUP BYを使うときに GROUP BY posts.id か GROUP BY categories_posts.post.idのどちらを使えば良いか?また、上記のSQL文のどこに記載したら良いか?

ご回答よろしくお願い致します。

質問者からの補足コメント

  • yambejp様

    早速のご回答ありがとうございます。

    SQLを使う目的をしっかり説明すればよかったのですが、抜けておりました。

    フォームのチェクボックスでカテゴリーをチェックボックス(複数可)で選んでそれに該当するpostsの一覧を表示させるというプログラムを作っておりました。
    postsの一覧を表示させるのにあたり、postsが重複するものは1つだけ表示させるようにしたいと思いました。

    このような目的でSQLを作る場合の方法を教えていただければと思います。
    よろしくお願いいたします。

    No.1の回答に寄せられた補足コメントです。 補足日時:2015/09/09 16:08
  • うれしい

    yambejp様

    ご回答ありがとうございます。
    上記のSQL文で求める結果となりました。カテゴリーの絞り込みで、WHERE categories_posts.category_id IN (1,2,3)を追加して、POSTに対応するカテゴリーを取り出す GROUP_CONCAT というものを見つけたのですが、これを使って下記のようなデータを作りたいと思います。
    1 | カテゴリー名1 カテゴリー名2 |
    2 | カテゴリー名2 カテゴリー名3 |

    作成していただいたSQL文に どのようにGROUP_CONCATを加えれば良いか教えていただければと思います。

    GROUP_CONCATはGROUP BYと一緒に使ってWHEREをHAVINGにするというところまではわかったのですが、うまく動かなくて困っております。

    No.2の回答に寄せられた補足コメントです。 補足日時:2015/09/09 20:28

A 回答 (3件)

>POSTに対応するカテゴリーを取り出す GROUP_CONCAT というものを見つけたのです



いや・・・#1でGROUP_CONCAT提示していますよね?

>GROUP_CONCATはGROUP BYと一緒に使ってWHEREをHAVING

ちょっと違うかも。この場合集計して抜き出すのではなく結合する際に絞り込むのが妥当。
JOINする際に条件節を追加します。具体的にはこう

SELECT p.id as pid,group_concat(c.name) as cname
FROM posts as p
INNER JOIN categories_posts as cp ON cp.post_id = p.id
AND cp.id IN (1,2,3)
INNER JOIN categories as c ON cp.category_id = c.id
GROUP BY pid;

ただし、普通に考えればcategoriesのidで絞り込むことはあっても
categories_postsのidで絞り込みをすることはありえない
categories_postsはpostsとcategoriesの組み合わせを決めるテーブルなので
そのidはprimary keyにあたるユニークを担保するものです。
検索の際にcategories_postsのidを意識することはまずないはずです。
    • good
    • 0
この回答へのお礼

yambejp様

何度も丁寧なご回答ありがとうございます。求める結果を得ることができました。

GROUP_CONCATの件、失礼いたしました。yambejp様からご提示いただいたソースで知ってウェブで情報を探したものでした。今回の件で3日間ほど苦戦しており、睡眠不足でボケておりました。申し訳ありません!

自分一人では解決にいつまでかかったことやら・・・
お力をお貸し頂き感謝です。

3つのテーブルの連結は初めてだったので苦労しましたが、だいぶ理解が進みました。
INNER JOIN はテーブルをつなぐだけに使用すると思っていたのですが、ここでもANDを使って絞り込んだりできるんですね。

お礼日時:2015/09/10 15:48

うーん、categoriesからpostsを絞り込むイメージでしょうか?



表示するのがpostsのみでよければ一般にdistinctをつかいます

SELECT distinct p.id as pid,p.name as pname
FROM posts as p
INNER JOIN categories_posts as cp ON cp.post_id = p.id
INNER JOIN categories as c ON cp.category_id = c.id
この回答への補足あり
    • good
    • 0

>postsのデータが重複して取り出されるので、重複するpostsを1つにまとめたい。



SQL的に意味がわからないですね
posts.idでgroup by したら複数あるcategoriesデータはどう表示したいのでしょうか?

かりにcategoriesのnameだけ羅列してよいならこんな感じ?
なおつなげる順番はそれほど気にする必要はありませんが
今回のケースだと意味合い的にpostsからつなげた方がわかりやすいかもしれません

SELECT p.id as pid,p.name as pname,group_concat(c.name) as cname
FROM posts as p
INNER JOIN categories_posts as cp ON cp.post_id = p.id
INNER JOIN categories as c ON cp.category_id = c.id
group by pid
この回答への補足あり
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す