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

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

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

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

Q&A

1回答

2301閲覧

Mysql 取得する値での重複は3つまで取得できるSELECT文を作りたい

K_T_T_K

総合スコア231

MySQL

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

0グッド

0クリップ

投稿2015/03/16 07:18

SELECT文を使って重複3つまで取得し4つ以上は取得しないSQLを作りたいです。
具体的に、
users(ユーザー)テーブル/goods(商品)テーブル/orders(注文履歴)テーブル、goodsテーブルがあり
これらを結合して
ユーザー名、商品名、購入時間を取得してきているのですが、
30件取得した中で、ユーザーが同じ商品名を3つ以上購入していた場合3つまでは取得するようにし、4つ以上からは取得しないようなSQLを作りたいです。

現在のSQLです。

lang

1SELECT u.user_name, g.goods_name,o.date_time 2FROM users as u 3JOIN order as o 4ON u.user_id = o.user_id 5JOIN goods as g 6ON o.order_id = g.id 7ORDER BY o.order_id DESC 8LIMIT 30

以上宜しくお願いします。

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

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

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

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

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

guest

回答1

0

素直なSQLでは、おそらく記述できないので、本来であればホスト言語側で処理するのがよいと思われますが、いくつかの前提を置けば、以下のように書いてもよいかと思います。

SELECT
u.user_name,
g.goods_name,
LEFT(GROUP_CONCAT(DISTINCT o.date_time ORDER BY o.date_time DESC SEPARATOR ','), 19 * 3 + 2)
FROM users AS u
LEFT JOIN order AS o
ON o.user_id = u.user_id
INNER JOIN goods AS g
ON g.id = o.order_id
GROUP BY u.user_name, g.goods_name;

まず、
order テーブルの date_time がDATETIME型であること
・取得結果は、ユーザー名、商品名の組み合わせを一意とすること
・直上の要件により、購入時刻が直近から降順で3件以内で取得できること
という形に要件を変形させます。

いくつか元のSQLで理解できなかったのが、
goods.idorder.order_id に結合可能だとすると購入IDがPKにならないのではないか
・発注時刻でORDER BYするのあれば、直近から降順になるべきではないのか
といったあたりですが、そこは適宜検討していただくとして。

キモは、
LEFT(GROUP_CONCAT(DISTINCT o.date_time ORDER BY o.date_time DESC SEPARATOR ','), 19 * 3 + 2)
の部分です。MySQLやSQLiteに実装されている集約関数なのですが(DB2などその他のDBではLIST関数として実装されていることがある)、これは、セパレータで連結された文字列として集約された指定フィールドの値群を得る関数です。LEFTは指定したインデクスより右にある文字列をトリミングする関数で、
19 * 3 + 2
については、
DATETIME型の文字数 * 取得したい上限件数 + 含まれるセパレータの文字数
という意味合いになります。

細かくは調整していただければ(NULL値についてはCOALESCE関数で空文字列に丸めるなど)、そこそこ実用になるのではないでしょうか。

投稿2015/03/17 08:15

BetaNews

総合スコア51

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問