LEFT JOIN および GROUP_CONCAT からの重複データのトラブルシューティング
LEFT JOINs
、GROUP BY
、GROUP_CONCAT
を使用して各ユーザーの上位タグとカテゴリを収集するクエリでは、予期せず重複したエントリが生成されます。
重複の問題を理解する
問題は、複数の LEFT JOINs
がユーザー、タグ、カテゴリ間に多対多の関係を作成することに起因します。 これにより、ユーザーごとに複数の行が作成され、それぞれが異なるタグとカテゴリの組み合わせを表します。 次に、GROUP BY
がこれらを集約し、GROUP_CONCAT
内に重複したアイテムが生成されます。
解決策: GROUP_CONCAT で DISTINCT を使用する
重複を排除するには、DISTINCT
関数内に GROUP_CONCAT
キーワードを追加します。これにより、一意のタグとカテゴリのみが連結されるようになります:
<code class="language-sql">SELECT q1.user_id, q1.user_name, q1.score, q1.reputation, SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT q2.tag ORDER BY q2.tag_reputation DESC SEPARATOR ','), ',', 2) AS top_two_tags, SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT q3.category ORDER BY q3.category_reputation DESC SEPARATOR ','), ',', 2) AS category FROM ...</code>
代替: よりクリーンな集計のためのサブクエリ
代替戦略では、LEFT JOIN
と GROUP BY
の組み合わせを完全に回避します。 サブクエリ (より複雑なシナリオの場合は CTE) を使用すると、より制御された集計が可能になります。
<code class="language-sql">SELECT u.user_id, u.user_name, u.score, u.reputation, (SELECT GROUP_CONCAT(tag ORDER BY tag_reputation DESC SEPARATOR ',') FROM post_tag WHERE user_id = u.user_id LIMIT 2) AS top_two_tags, (SELECT GROUP_CONCAT(category ORDER BY category_reputation DESC SEPARATOR ',') FROM post_category WHERE category_id = u.category_id LIMIT 2) AS category FROM users u</code>
この方法では、集計がユーザーごとに独立して行われるため、以前の重複が防止されます。 データベースの構造とクエリの複雑さに最も適したアプローチを選択してください。
以上がLEFT JOIN と GROUP_CONCAT が重複した結果を生成するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。