2016-09-19 66 views
0

我正在嘗試join單行的多行信息,但似乎每次在其中一個聯接中存在更多行時會相乘。MySQL - 多行聯接多行到單行

我的表結構如下:

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是重複的,所以如果一篇新聞文章我s的3組中,user_groups也將成倍增加,並顯示5,6,6,6,5,5之類的內容。

如何分組這些組,使它們只顯示一次?

這裏的最終目的是比較news_groupsuser_groups。因此,如果至少有一個組匹配(意味着用戶具有足夠的權限),則返回true,否則返回false。我也不知道該怎麼做,但是,我認爲我應該首先對分組進行分類,因爲一旦分組數量變大,就會有不必要的大量相同的數據被選中。

謝謝!

回答

1

最簡單的方法是使用DISTINCT 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; 

二,CROSS JOIN(或相當於JOIN沒有ON條款)是沒有意義的。通常情況下,我希望有一個連接條件到其他表中的一個。

+0

謝謝,由於某種原因,「DISTINCT」甚至沒有出現在我的腦海裏。你說得很好,我可以在查詢之前準備'user_groups',而不是'member_id'。在那種情況下,我怎麼能用這個來與'news_groups'進行交叉檢查?對於單個值,我可以使用'IN',但是如何使用'或'功能來檢查多個值(這樣可以匹配任何值)? – Giedrius

1

使用的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 
...