2016-09-19 12 views
0

私はjoinの単一行の情報を複数行にしようとしていますが、ジョインの1つに多くの行があるたびに倍増しているようです。次のように複数の行から単一の行に複数回ジョインする

私のテーブルの構造は次のとおりです。

news 
id | title | public 
------------------------ 
1 | Test | 0 


news_groups_map 
id | news_id | members_group_id 
------------------------------------ 
1 | 1  | 5 
2 | 2  | 6 


members_groups_map 
id | member_id | group_id 
------------------------------ 
1 | 750  | 5 
2 | 750  | 6 

私がこれまで持っているクエリは次のとおりです。

SELECT 
n.title, 
n.public, 

CAST(GROUP_CONCAT(ngm.members_group_id) AS CHAR(1000)) AS news_groups, 
CAST(GROUP_CONCAT(member_groups.group_id) AS CHAR(1000)) AS user_groups 

FROM news n 

LEFT JOIN news_groups_map ngm ON n.id = ngm.news_id 

JOIN (
    SELECT group_id 
    FROM members_groups_map 
    WHERE member_id = 750 
) member_groups 

WHERE n.public = 0 
GROUP BY n.id 

次のようにしかし、結果は次のとおりです。

title | public | news_groups | user_groups 
------------------------------------------------- 
Test | 0  | 5,6,5,6  | 6,6,5,5 

ご覧のとおり、news_groupuser_groupsは重複しているので、ニュース記事i sの3つのグループでは、user_groupsも同様に乗算され、5,6,6,6,5,5のようなものが表示されます。

これらのグループはどのようにグループ化でき、一度表示されるだけですか?

最終的な目標は、news_groupsuser_groupsを比較することです。したがって、少なくとも1つのグループが一致する場合(ユーザーに十分なアクセス権があることを意味します)、trueが返され、それ以外の場合はfalseのブール値が必要です。私はそれをどうやって行うのかわかりませんが、一度グループの数が増えると、選択された同じデータが不必要にたくさんあるため、グループ化を最初に並べ替えるべきだと思いました。

ありがとうございます!

答えて

1

で最も簡単な方法は、distinctを使用することです:

SELECT n.title, n.public, 
     GROUP_CONCAT(DISTINCT ngm.members_group_id) AS news_groups,  
     GROUP_CONCAT(DISTINCT mg.group_id) AS user_groups 
FROM news n LEFT JOIN 
    news_groups_map ngm 
    ON n.id = ngm.news_id CROSS JOIN 
    (SELECT group_id 
     FROM members_groups_map 
     WHERE member_id = 750 
    ) mg 
WHERE n.public = 0 
GROUP BY n.id; 

このクエリは、実際に意味がありません。まず、副問合せは必要ありません。

SELECT n.title, n.public, 
     GROUP_CONCAT(DISTINCT ngm.members_group_id) AS news_groups,  
     GROUP_CONCAT(DISTINCTD mg.group_id) AS user_groups 
FROM news n LEFT JOIN 
    news_groups_map ngm 
    ON n.id = ngm.news_id CROSS JOIN 
    members_groups_map mg 
    ON member_id = 750 
WHERE n.public = 0 
GROUP BY n.id; 

第二に、(ON句なしまたは同等に、JOINCROSS JOINは意味がありません。通常、私は他のテーブルの1つにジョイン条件を期待します。

+0

「DISTINCT」は何らかの理由で私の頭にさえ届かなかった。あなたは良い点を作っています。 'member_id'の代わりに' user_groups'をクエリの前に置くことができます。その場合、どうすれば 'news_groups'を使ってクロスチェックすることができますか?単一の値の場合、私は 'IN'を使うことができますが、' or'の機能で複数の値をチェックするにはどうすればいいですか? – Giedrius

1

使用DISTINCT GROUP_CONCAT

... 
CAST(GROUP_CONCAT(DISTINCT ngm.members_group_id) AS CHAR(1000)) AS news_groups, 
CAST(GROUP_CONCAT(DISTINCT member_groups.group_id) AS CHAR(1000)) AS user_groups 
... 
関連する問題