質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

334閲覧

MySQLで「タグを持つ記事」を取得したい

hotaruika

総合スコア57

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2020/10/09 03:59

編集2020/10/09 04:29

###前提・実現したいこと
wp_posts、wp_tags、wp_tag_holders、という3つのテーブルがあります。(wp_という接頭辞は気にしないでください。)

tags.tag_name='red' and tags.tag_name='purple'のように指定して「redとpurpleのタグを持つ記事」という取得をしたいのですが…

###発生している問題
…ですが、whereの指定がよくわからず、取得件数が0件になってしまいます。

###欲しい結果
「redとpurpleのタグを持つ記事」とは「tag_id=1とtag_id=5を持つ記事」になります。
つまり「post_id=1とpost_id=5の記事」であり以下の結果が欲しいです。

IDcontent
1赤くて緑で紫
5赤くて紫

###テーブル設計
CREATE、INSERTです。

MySQL

1CREATE TABLE wp_posts ( 2 `ID` int, 3 `content` varchar(100), 4 PRIMARY KEY (`ID`) 5); 6INSERT INTO wp_posts 7 (`ID`, `content`) 8VALUES 9 (1, '赤くて緑で紫'),(2, '緑で紫'),(3, '赤'),(4, '青'),(5, '赤くて紫') 10; 11 12CREATE TABLE wp_tags ( 13 `ID` int, 14 `tag_name` varchar(10), 15 PRIMARY KEY (`ID`), 16 INDEX index_wp_tags_1 (`tag_name`) 17); 18INSERT INTO wp_tags 19 (`ID`, `tag_name`) 20VALUES 21 (1, 'red'),(2, 'green'),(3, 'blue'),(4, 'yellow'),(5, 'purple') 22; 23 24CREATE TABLE wp_tag_holders ( 25 `tag_ID` int, 26 `post_ID` int, 27 CONSTRAINT foreign_wp_tag_holders_01 FOREIGN KEY (`tag_ID`) REFERENCES wp_tags(`ID`), 28 INDEX index_wp_tag_holders_1 (`post_ID`) 29); 30INSERT INTO wp_tag_holders 31 (`tag_ID`,`post_ID`) 32VALUES 33 (1, 1),(2, 1),(5, 1),(2, 2),(5, 2),(1, 3),(3, 4),(1, 5),(5, 5) 34; 35

###取得のソースコード
以下で取得件数は0件でした。

MySQL

1select 2post.ID, 3post.content 4 5from 6wp_posts post 7left join 8wp_tag_holders tag_holders ON tag_holders.post_ID=post.ID 9left join 10wp_tags tags ON tags.ID=tag_holders.tag_ID 11 12where 13tags.tag_name='red' and tags.tag_name='purple'

###試したこと
上のjoinしたものをwhereで指定できないのだと思い、joinの方向をやめて、次のようにINで指定するように試みましたが、こちらもエラーなどはないのですが、取得件数は0件でした。

MySQL

1select 2post.ID, 3post.content 4 5from 6wp_posts post 7 8where post.ID IN ( 9 select 10 tag_holders.post_ID 11 from 12 wp_tag_holders tag_holders 13 left join 14 wp_tags tags ON tags.ID=tag_holders.tag_ID 15 where 16 tags.tag_name='red' and tags.tag_name='purple' 17) 18 19

###バージョン
MySQLのバージョンは少し古めで5.6になります。
宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/10/09 04:02

WordPress前提でしたら「WordPress」はタグにあったほうが良いと思います。 「wp_という接頭辞は気にしないでください。」と仰いますが、構成がそれであれば前提条件として必要に思います。
guest

回答2

0

「redとpurpleのタグを持つ記事」というのは、「redのタグを持つ記事」と「purpleのタグを持つ記事」が共に存在しているという独立した事象である事を条件にします。

SQL

1select ID, content 2from wp_posts post 3where exists ( 4 select 1 5 from wp_tag_holders tag_holders 6 left join wp_tags tags 7 ON tags.ID=tag_holders.tag_ID 8 where tag_holders.post_ID=post.ID 9 and tags.tag_name='red' 10 ) 11 and exists( 12 select 1 13 from wp_tag_holders tag_holders 14 left join wp_tags tags 15 ON tags.ID=tag_holders.tag_ID 16 where tag_holders.post_ID=post.ID 17 and tags.tag_name='purple' 18 )

投稿2020/10/09 06:21

sazi

総合スコア25206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hotaruika

2020/10/09 07:35

仰る書き方で考えていた通りにできました。タグの数だけselectが発生せざるを得ないのですか。タグが増えるほどかなり遅くなりそうですが、仕方ないですね。ありがとうございます。
sazi

2020/10/09 07:53 編集

条件用のテーブルなどがあれば別ですが、条件が動的である以上可変部分を少なくすることは出来ても、無くす事はできません。
guest

0

ベストアンサー

レコード単位でredかつpurpleのデータは存在しないですから
どういう結果をほしいかわかりませんがとりあえずandをorに変えるところから

投稿2020/10/09 04:05

yambejp

総合スコア115008

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2020/10/09 04:26

ざっと条件を見直してみるとこんな感じでしょうか? select * from wp_posts as t3 where id in( select t2.tag_id from wp_tags as t1 inner join wp_tag_holders as t2 on t1.id=t2.post_id and t1.tag_name in('red','purple') group by tag_id having count(*)=2 )
sazi

2020/10/09 06:24

それだと、redやpurple片方だけで2件あってもHITしちゃいます。
yambejp

2020/10/09 06:45

> redやpurple片方だけで2件あっても たしかにテーブル側で制限してないですが、普通は中間テーブルは同じデータを もつことを想定していないんですけどね、一応ダブりを想定するならこう? select * from wp_posts as t3 where id in( select t2.tag_id from wp_tags as t1 inner join wp_tag_holders as t2 on t1.id=t2.post_id and t1.tag_name in('red','purple') group by tag_id having count(distinct post_id)=2 )
hotaruika

2020/10/09 07:40 編集

ありがとうございます。yambejp様のコードでも実現できました。select回数が少ない分だけsazi様のコードより早く済みそうに思えましたが、質問がございます。
hotaruika

2020/10/09 07:40

「普通は中間テーブルは同じデータを もつことを想定していない」というのは、どういう意味でしょうか? 質問のCREATEには何か問題というか、「普通でない」ような状態になっているのでしょうか?
yambejp

2020/10/09 07:48

wp_tag_holdersはwp_postsとwp_tagsをリレーションするテーブルですよね? 仮に2,1で連携されているデータにもう一つ2,1を連携させる意味がありません。 したがってtag_ID,post_IDをつかって複合unique属性を付けておくのが妥当です。 しかしそのように設定されていないのであえてdistinctをかましたcountをつかって 処理をしています
hotaruika

2020/10/09 07:57

はい、リレーションするテーブルになります。 たびたび理解が至らず誠に申し訳ございませんが、以下の引用はどの部分のことでしょうか? >仮に2,1で連携されているデータにもう一つ2,1を連携させる意味がありません wp_tag_holdersのレコードは (1, 1),(2, 1),(5, 1),(2, 2),(5, 2),(1, 3),(3, 4),(1, 5),(5, 5) となっており、「2,1」は一つしかないと思うのですが、「もう一つ2,1」とは? 私としても重複は望んではおりませんので、どの部分のことを仰っているのか理解したいのですが…
yambejp

2020/10/09 08:02

> 「もう一つ2,1」とは? もう一つ2,1を追加する「可能性がある」ということです saziさんの指摘もそこに帰結します。 かりに2,1のレコードを追加してみると、私の最初のSQLがNGで新しいSQLがOKなのが 確認できると思います
hotaruika

2020/10/09 08:07

なるほど。yambe様は質問にドンピシャでお答え下さったのに対し、sazi様は質問で複合ユニークがないことから「可能性がある」を想定し先見に富んだお答えを下さったわけですね。 今回は複合ユニークとすべきでしたので、yambe様の13:26が適当かもしれません。 高レベルなお二方のご回答は大変刺激になりました。どうもありがとういございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問