🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
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回答

1238閲覧

「どのwhereで取得されたレコードか?」を、取得結果に示したい(MySQL)

premiummalts

総合スコア3

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/12/07 23:16

編集2020/12/08 00:19

###前提・実現したいこと
MySQLのwhereで「タグ1とタグ2を持つ記事」などの条件で取得しています

下記のソースコードで取得結果となるIDは 2,4,8,9,10 という5件です

この取得結果に、「このレコードはタグ1を持つ記事として取得されました」ということを示すことはできますか?

###最終的な目的
最終的な目的としてはフロントへの出力を次のように、タグごとにわけることです

------------
【タグ1を持つ記事一覧】
2,4,8,10

【タグ2を持つ記事一覧】
9
------------

###ソースコード
現状はこのようなSQLを書いていて、

sql

1select p.ID, p.contents 2from posts p 3left join tag_relations tr ON tr.contents_ID = p.ID 4left join tags t ON t.ID = tr.tags_ID 5where t.tag_name IN ( 'タグ1', 'タグ2' ) # 指定タグを持っている 6AND p.ID NOT IN ( 1 ) # 指定記事を除外 7group by p.ID

###ソースコードの結果
で、次のレコードが取得される状況ですが、

IDcontents
2#タグ1 を持っている記事2の本文です
4#タグ1 と #タグ3 と #タグ4 を持っている記事4の本文です
8#タグ1 を持っている記事8の本文です
9#タグ2 と #タグ4 を持っている記事9の本文です
10#タグ1 と #タグ2 と #タグ6 を持っている記事10の本文です

###欲しい結果
ここに次のように「このレコードはタグ1を持つ記事として取得されました」などの「取得経緯のtag_ID」を示したいのです

IDcontents取得経緯のtag_ID
2#タグ1 を持っている記事2の本文です1
4#タグ1 と #タグ3 と #タグ4 を持っている記事4の本文です1
8#タグ1 を持っている記事8の本文です1
9#タグ2 と #タグ4 を持っている記事9の本文です2
10#タグ1 と #タグ2 と #タグ6 を持っている記事10の本文です1

【※】post_ID=10はタグ1もタグ2も持っていますが、タグ1側を優先したいです

###テーブル
そしてテーブルはこうです

sql

1-- 記事 2CREATE TABLE posts 3 (`ID` int, `user_ID` int, `contents` varchar(100)) 4; 5INSERT INTO posts 6 (`ID`, `user_ID`, `contents`) 7VALUES 8 (1, 10, '#タグ1 と #タグ2 を持っている記事1の本文です'), 9 (2, 20, '#タグ1 を持っている記事2の本文です'), 10 (3, 30, '記事3の本文です'), 11 (4, 10, '#タグ1 と #タグ3 と #タグ4 を持っている記事4の本文です'), 12 (5, 30, '#タグ5 を持っている記事5の本文です'), 13 (6, 40, '記事6の本文です'), 14 (7, 10, '記事7の本文です'), 15 (8, 50, '#タグ1 を持っている記事8の本文です'), 16 (9, 10, '#タグ2 と #タグ4 を持っている記事9の本文です'), 17 (10, 20, '#タグ1 と #タグ2 と #タグ6 を持っている記事10の本文です') 18; 19 20-- タグ 21CREATE TABLE tags 22 (`ID` int, `tag_name` varchar(100)) 23; 24INSERT INTO tags 25 (`ID`, `tag_name`) 26VALUES 27 (1, 'タグ1'), 28 (2, 'タグ2'), 29 (3, 'タグ3'), 30 (3, 'タグ4'), 31 (3, 'タグ5'), 32 (3, 'タグ6') 33; 34 35-- タグリレーション 36CREATE TABLE tag_relations 37 (`tags_ID` int, `contents_ID` int ) 38; 39INSERT INTO tag_relations 40 (`tags_ID`, `contents_ID` ) 41VALUES 42 # contents_ID=1が、tag_ID=1とtag_ID=2を持っている 43 (1, 1), (2, 1), 44 # contents_ID=2が、tag_ID=1を持っている 45 (1, 2), 46 # contents_ID=4が、tag_ID=1とtag_ID=3とtag_ID=4を持っている 47 (1, 4), (3, 4), (4, 4), 48 # contents_ID=5が、tag_ID=5を持っている 49 (5, 5), 50 # contents_ID=8が、tag_ID=1を持っている 51 (1, 8), 52 # contents_ID=9が、tag_ID=2とtag_ID=4を持っている 53 (2, 9), (4, 9), 54 # contents_ID=10が、tag_ID=1とtag_ID=2とtag_ID=6を持っている 55 (1, 10), (2, 10), (6, 10) 56;

###試したこと
最終的な目的のためには、クエリを一つにまとめずアプリケーション側で二つ実行すればいいのですが、まずそれはなしで、一つのクエリで実現したいと考えています

ならばと、二つをそのまま一つにまとめて、つまりunionで次のようにまとめてみれば実現できるか?と思ったのですが…

惜しくも【※】の部分が欲しい結果とは微妙に異なりまして、ID=10について、「取得経緯のtag_ID」が1でなく2になってしまう結果でした(そもそもunionはあまり推奨されないようですし、他の方法を探しています)

sql

1select p.ID, p.contents, '1' AS 取得経緯のtag_ID 2from posts p 3left join tag_relations tr ON tr.contents_ID = p.ID 4left join tags t ON t.ID = tr.tags_ID 5where t.tag_name IN ( 'タグ1' ) # 指定タグを持っている 6AND p.ID NOT IN ( 1 ) # 指定記事を除外 7group by p.ID 8 9union 10 11select p.ID, p.contents, '2' AS 取得経緯のtag_ID 12from posts p 13left join tag_relations tr ON tr.contents_ID = p.ID 14left join tags t ON t.ID = tr.tags_ID 15where t.tag_name IN ( 'タグ2' ) # 指定タグを持っている 16AND p.ID NOT IN ( 1 ) # 指定記事を除外 17group by p.ID

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

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

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

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

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

maisumakun

2020/12/08 00:33 編集

> ID=10について、「取得経緯のtag_ID」が1でなく2になってしまう結果でした このような場合はどちらを優先させるか、決まっていますか?
premiummalts

2020/12/08 00:36

失礼致しました 小さいものを優先したいと考えています
guest

回答2

0

ベストアンサー

group_concat()を使用してtag_name を列挙します。
質問のSQLでは、group by でcontentsが指定されていませんので明示した上でのSQLは以下です

SQL

1select p.ID, p.contents, group_concat(t.tag_name) grp_tag 2from posts p 3left join tag_relations tr ON tr.contents_ID = p.ID 4left join tags t ON t.ID = tr.tags_ID 5where t.tag_name IN ( 'タグ1', 'タグ2' ) # 指定タグを持っている 6AND p.ID NOT IN ( 1 ) # 指定記事を除外 7group by p.ID, p.contents

投稿2020/12/08 00:24

sazi

総合スコア25327

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

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

premiummalts

2020/12/08 00:58

ありがとうございます!group_concatでやらせていただきます
premiummalts

2020/12/08 01:00

すみません、「group by でcontents」ということですが、これはなぜ必要なのですか?あってもなくても同じ結果のようですが、ない場合にどのような不具合がありえるのでしょうか?
sazi

2020/12/08 01:19

group byする時、select項目を指定する場合にはそのselect項目はgroup byに指定しなければなりません。 mysqlの場合group byの指定が無いselect 項目は主に先頭のみが表示されます。(モードによる) 意図が分かりませんでしたので、不要なら除外して下さい。
premiummalts

2020/12/08 01:49

質問のselect項目にはcontentsがありますから、それを表示するためには本来はgroup byに指定しなければならないということですよね? しかしmysqlの場合は先頭のみが表示されるためその本来の指定は不要となり、group byに指定せずとも普通にcontentsが表示できている…という感じでしょうか? なんとなくwわかりました!ありがとうございました 今後は念のため指定しておくようにします
guest

0

t.tag_nameを表示すればよいかと。

投稿2020/12/07 23:27

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

premiummalts

2020/12/07 23:29

ありがとうございます そうするとtag_nameは表示されますが、最終的な目的はどのようにしますか?
退会済みユーザー

退会済みユーザー

2020/12/07 23:33

SQL を組みなおしてください。
premiummalts

2020/12/07 23:34

ありがとうございます 他の方のご回答を待たせて頂きます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問