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

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

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

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

Q&A

0回答

619閲覧

n件ずつ、グループごとに取得したい(MySQL)

premiummalts

総合スコア3

MySQL

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

0グッド

0クリップ

投稿2020/12/08 05:59

編集2020/12/08 06:13

###実現したいこと
以下3つのテーブルがあります

・記事テーブル「posts」
・タグテーブル「tags」
・タグリレーションテーブル「tag_relations」

以下2つの条件で記事を取得したいです

【条件1】指定タグを持っている
【条件2】タグ単位で2件ずつ

###テーブル

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, '#タグ2 と #タグ3 と #タグ7 を持っている記事6の本文です'), 14 (7, 10, '#タグ2 と #タグ4 と #タグ8 を持っている記事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), `rank_weekly` int) 23; 24INSERT INTO tags 25 (`ID`, `tag_name`, `rank_weekly`) 26VALUES 27 (1, 'タグ1', 1), 28 (2, 'タグ2', 2), 29 (3, 'タグ3', 3), 30 (4, 'タグ4', 4), 31 (5, 'タグ5', 5), 32 (6, 'タグ6', 6), 33 (7, 'タグ7', 7), 34 (8, 'タグ8', 8) 35; 36 37-- タグリレーション 38CREATE TABLE tag_relations 39 (`tags_ID` int, `contents_ID` int ) 40; 41INSERT INTO tag_relations 42 (`tags_ID`, `contents_ID` ) 43VALUES 44 # contents_ID=1が、tag_ID=1とtag_ID=2を持っている 45 (1, 1), (2, 1), 46 # contents_ID=2が、tag_ID=1を持っている 47 (1, 2), 48 # contents_ID=4が、tag_ID=1とtag_ID=3とtag_ID=4を持っている 49 (1, 4), (3, 4), (4, 4), 50 # contents_ID=5が、tag_ID=5を持っている 51 (5, 5), 52 # contents_ID=6が、tag_ID=2とtag_ID=3とtag_ID=7を持っている 53 (2, 6), (3, 6), (7, 6), 54 # contents_ID=7が、tag_ID=2とtag_ID=4とtag_ID=8を持っている 55 (2, 7), (4, 7), (8, 7), 56 # contents_ID=8が、tag_ID=1を持っている 57 (1, 8), 58 # contents_ID=9が、tag_ID=2とtag_ID=4を持っている 59 (2, 9), (4, 9), 60 # contents_ID=10が、tag_ID=1とtag_ID=2とtag_ID=6を持っている 61 (1, 10), (2, 10), (6, 10) 62;

現状のソースコード

まずは【条件1:指定タグを持っている】だけを採用した場合を考えまして、こちらになります

sql

1select p.ID 2, p.contents 3, group_concat(t.tag_name separator ' ') as tag_names 4from posts p 5left join tag_relations tr ON tr.contents_ID = p.ID 6left join tags t ON t.ID = tr.tags_ID 7where t.tag_name IN ( 'タグ1', 'タグ2', 'タグ4', 'タグ7' ) # タグ名を指定 8AND p.ID NOT IN ( 1 ) # 記事IDを除外 9group by p.ID, p.contents

↓結果はこうなります

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

###求める結果
あとは上記に【条件2:タグ単位で2件ずつ】という条件を加味して、次の結果を得たいという状況です

※上記でID=6はタグ2とタグ7を持っていますが、ここでタグ2を優先するとタグ7の記事がなくなってしまうので、ID=6はタグ7の記事として取得される。という流れで下記の結果を得たいです

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

###試したこと
しかしこの結果の取得が大変難しく思います

例えば最後に

sql

1limit 2

と指定すれば、ID=2,4しか取得できませんし、

また例えば

sql

1having count(p.ID) <= 2

というような指定をしても、結果は条件1の場合と変わらずでした

あとは、全体をwrapと囲んだサブクエリを作り、それに対してgroup byをかけて以下のようにしてみたのですが、やはりこちらも求める結果になりません

sql

1select * 2from ( 3 select p.ID 4 , p.contents 5 , group_concat(t.tag_name separator ' ') as tag_names 6 from posts p 7 left join tag_relations tr ON tr.contents_ID = p.ID 8 left join tags t ON t.ID = tr.tags_ID 9 where t.tag_name IN ( 'タグ1', 'タグ2', 'タグ4', 'タグ7' ) # タグ名を指定 10 AND p.ID NOT IN ( 1 ) # 記事IDを除外 11 group by p.ID, t.tag_name 12) AS wrap 13group by wrap.ID

###バージョン情報
ちなみに使用しているのは MariaDB の v10.0.33 で、これはMySQLでいうと v5.5 に相当するものになります

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

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

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

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問