简体   繁体   中英

MySQL: why does GROUP_CONCAT lose rows in my multiple join query?

I'm trying to fetch all the rows from table_m which also have an index in table_mi and I'm expecting to get 2 rows as a result (with m.id=3 and m.id=9) - but if I add GROUP_CONCAT to my select then I only get one row returned. Am I having a misshap somewhere within those joins of mine?

Query:

SELECT 
    m.id,
    m.name,
    m.keyword,
    IFNULL(GROUP_CONCAT(r.keyword),'TEST') AS restrictions
FROM 
    table_m AS m 
INNER JOIN
    table_mi as mi ON m.id=mi.m_id
LEFT JOIN
    table_ri as ri ON m.id=ri.m_id
LEFT JOIN
    table_r AS r ON ri.r_id=r.id
WHERE 
    (
        m.id>0
        AND m.active=1  
        AND mi.p_id=0
        AND (mi.pa_id="11" OR (mi.pa_id=0 AND mi.id!=0)) 
        AND mi.u_id=IF((SELECT id FROM table_mi WHERE p_id=0 AND pa_id="11" AND u_id="2")>0,"2",0)
    ) OR mi.id=0 
ORDER BY
    mi.priority;

This is what I'm getting as a result:

ID  NAME    KEYWORD RESTRICTIONS
9   test_a  key_a   r_key_2,r_key_3,r_key_4

This is what I'm expecting:

ID  NAME    KEYWORD RESTRICTIONS
9   test_a  key_a   r_key_2,r_key_3,r_key_4
3   test_b  key_b   TEST

Please see my full example with schema on sql fiddle: http://sqlfiddle.com/#!2/359d9/1

GROUP_CONCAT is an aggregate function. It will bring back a single row UNLESS you specify a GROUP BY clause (with any fields that are not in the GROUP BY being aggregate fields)

Before the ORDER BY add the following:-

GROUP BY m.id,  m.name, m.keyword

That said it looks like you might want to use CONCAT to join 2 values together rather than GROUP_CONCAT

As an aside, your SQL might be easier to read if you eliminate the subselect. Assuming it is bringing back a single record then possibly as follows

SELECT 
    m.id,
    m.name,
    m.keyword,
    IFNULL(GROUP_CONCAT(r.keyword),'TEST') AS restrictions
FROM 
    table_m AS m 
INNER JOIN
    table_mi as mi ON m.id=mi.m_id
LEFT JOIN
    table_ri as ri ON m.id=ri.m_id
LEFT JOIN
    table_r AS r ON ri.r_id=r.id
LEFT OUTER JOIN 
    table_mi AS mi2 ON mi2.p_id=0 AND mi2.pa_id="11" AND mi2.u_id="2"
WHERE 
    (
        m.id>0
        AND m.active=1  
        AND mi.p_id=0
        AND (mi.pa_id="11" OR (mi.pa_id=0 AND mi.id!=0)) 
        AND mi.u_id=IF(mi2.id >0,"2",0)
    ) OR mi.id=0 
ORDER BY
    mi.priority;

You do no need GROUP_CONCAT to achieve what you want.

Instead of :

IFNULL(GROUP_CONCAT(r.keyword),'TEST') AS restrictions

use

IFNULL(r.keyword,'TEST') AS restrictions

OR:

Keep the query as it is and add GROUP BY m.id before ORDER BY

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM