Sample Header Ad - 728x90

Multiple GROUP_CONCAT statements within single MySQL Query

0 votes
1 answer
1872 views
I have a table where each record has a one to many relationship with 3 other tables (with further one to one branching) leading to many rows for each main record with many columns of duplicate information. In PHP, I take the result set and flatten it to a multidimensional array. I am weighing the benefits of rewriting the query to let MySQL do the flattening using GROUP_CONCAT statements. I'd end up with one row per main record with 3 fields of concatenated data (files, grades + pages, and categories). I am not using any GROUP BY statements; I'm only using GROUP_CONCAT to flatten. I've done this before for a single GROUP_CONCAT but am curious if this a "normal" use of the technology. I am asking from a design standards and maintainability point of view or if there are any gotchas I'm overlooking. Is it personal preference? Performance appears to be about the same. As I see it from a programming standpoint Benefits of GROUP_CONCAT: - no duplicated data to send across the internet - simplified processing in PHP: even though I have to massage the data afterwards using explode(), it seems less obtuse than the code I have to step through, compiling the distinct values of file, grade + page, and category for each record - the query actually appears to better represent what is happening by putting the many joins in context Downsides: - There are multiple columns being combined within the GROUP_CONCAT output, so complexity is added with delimiters and nested explode() statements needed in PHP to separate out the fields. - If it's not broken... I've been using the code without GROUP_CONCAT for many years. A pain to change, but I get there eventually. The query below is much simplified. The reason for the nested query is a calculation subquery I've removed. Query without GROUP_CONCAT SELECT g.gemid, g.title, gd.filename, gd.license, gp.grade, gp.page, gp.page2, gc.category, mg.topid, mg.title AS gradetitle, mp.license AS pagelicense, mp2.license AS page2license, mp.title AS pagetitle, mp2.title AS page2title FROM ( SELECT DISTINCT gems.gemid, gems.title, gp.sort FROM gems LEFT JOIN gempage gp ON gems.gemid = gp.gemid WHERE gp.grade = 1 ORDER BY gp.sort ) g LEFT JOIN gempage gp ON g.gemid = gp.gemid LEFT JOIN mgrade mg ON gp.grade = mg.name LEFT JOIN mpage mp ON gp.page = mp.name AND mg.gradeid = mp.gradeid LEFT JOIN mpage2 mp2 ON gp.page2 = mp2.name AND mp.pageid = mp2.pageid AND mg.gradeid = mp.gradeid LEFT JOIN gemcategory gc ON g.gemid = gc.gemid LEFT JOIN gemdetail gd ON g.gemid = gd.gemid WHERE gp.grade = 1 ORDER BY gp.sort Query with GROUP_CONCAT SELECT (SELECT GROUP_CONCAT(CONCAT_WS(":",IFNULL(filename,''), IFNULL(license,''))) FROM gemdetail gd WHERE g.gemid = gd.gemid) as filelist, (SELECT GROUP_CONCAT(category ORDER BY sort, gemcategoryid SEPARATOR ', ') FROM gemcategory gc WHERE gc.gemid = g.gemid) as catlist, (SELECT DISTINCT GROUP_CONCAT(CONCAT_WS(",", gp.grade, gp.page, IFNULL(gp.page2,''), mg.topid, IFNULL(mg.title,''), IFNULL(mp.license,''), IFNULL(mp.title,''), IFNULL(mp2.license,''), IFNULL(mp2.title,''))) FROM gempage gp LEFT JOIN mgrade mg ON gp.grade = mg.name LEFT JOIN mpage mp ON gp.page = mp.name AND mg.gradeid = mp.gradeid LEFT JOIN mpage2 mp2 ON gp.page2 = mp2.name AND mp.pageid = mp2.pageid AND mg.gradeid = mp.gradeid WHERE g.gemid = gp.gemid AND gp.grade = 1) as gradepage, g.gemid, g.title FROM ( SELECT DISTINCT gems.gemid, gems.title, gp.sort FROM gems LEFT JOIN gempage gp ON gems.gemid = gp.gemid WHERE gp.grade = 1 ORDER BY gp.sort ) g
Asked by mseifert (103 rep)
Dec 7, 2022, 10:51 PM
Last activity: Dec 8, 2022, 06:53 AM