2016-09-19 1 views
0

단일 행에 대한 정보의 여러 행을 join 시도하고 있지만 조인 중 하나가 더 많은 행이있을 때마다 곱하는 것 같습니다.MySQL - JOIN 여러 행을 단일 행 여러 번

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 그룹에 속하면 user_groups도 곱해지고 5,6,6,6,5,5과 같은 것을 보여줄 것입니다.

그룹을 그룹화하여 한 번만 표시되도록하려면 어떻게해야합니까?

궁극적 인 목표는 news_groupsuser_groups을 비교하는 것입니다. 따라서 적어도 하나의 그룹이 일치하면 (즉 사용자에게 충분한 권한이 있음을 의미) 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; 

둘째, (AN ON 절없이 또는 동등 JOIN)를 CROSS JOIN이 이해가되지 않습니다. 일반적으로 다른 테이블 중 하나에 대한 조인 조건이 필요합니다.

+0

감사합니다. 'DISTINCT'는 어떤 이유로 든 내 머리에 오지 않았습니다. 당신은 좋은 지적을하고,'user_groups'를'member_id' 대신에 쿼리하기 전에 준비 할 수 있습니다. 이 경우 어떻게'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 
... 
관련 문제