Preamble
This is the function MySQL GROUP CONCAT and how it can change the work with query results. Especially if the database is the data source for the application.
Database
I will use the Sakila sample database as a reference. The database includes a number of related tables on the subject of cinema: from actors and film studios to video distribution points. The full structure of this database can be seen on the MySQL development site.
Outdated grouping method
The GROUP BY operator is an excellent tool for selecting related data. But it is not suitable for accurate data sorting.
Let’s imagine that we are the owners of a film distribution point and wish to reward those customers who have taken many horror movies. To do this, we need to know which films each client has rented. One way to do this is to move the GROUP BY SELECT instruction to an attached request that returns user IDs that meet all requirements. It is then possible to limit the results of an external request to those clients whose IDs are part of the internal result set.
Below is the SQL code that performs this work without MySQL GROUP CONCAT SEPARATOR:
SELECT CONCAT(CU.last_name, ', ', CU.first_name) AS customer,
A.phone,
F.title,
date(R.rental_date) AS rental_date
FROM sakila.rental R
LEFT JOIN sakila.inventory I ON R.inventory_id = I.inventory_id
LEFT JOIN sakila.film F ON I.film_id = F.film_id
LEFT JOIN sakila.film_category FC on F.film_id = FC.film_id
LEFT JOIN sakila.category C ON FC.category_id = C.category_id
LEFT JOIN sakila.customer CU ON R.customer_id = CU.customer_id
LEFT JOIN sakila.address A ON CU.address_id = A.address_id
WHERE CU.customer_id in
(SELECT CU.customer_id)
FROM rental R
LEFT JOIN sakila.customer CU ON R.customer_id = CU.customer_id
LEFT JOIN sakila.inventory I ON R.inventory_id = I.inventory_id
LEFT JOIN sakila.film F ON I.film_id = F.film_id
LEFT JOIN sakila.film_category FC on F.film_id = FC.film_id
LEFT JOIN sakila.category C ON FC.category_id = C.category_id
WHERE C.name = "Horror"
GROUP BY CU.customer_id
HAVING COUNT(CU.customer_id) >= 3)
AND C.name = "Horror"
ORDER BY customer, title, rental_date DESC;
Receive the first three clients with the titles of the films rented and the dates:
customer phone title rental_date
—————————————————————-
ADAM, NATHANIEL 111177206479 ANALYZE HOOSIERS 2005-08-19
ADAM, NATHANIEL 111177206479 FREDDY STORM 2005-08-22
ADAM, NATHANIEL 111177206479 STRANGERS GRAFFITI 2005-08-23
ANDREW, JOSE 961370847344 EGYPT TENENBAUMS 2005-07-31
ANDREW, JOSE 961370847344 FIDELITY DEVIL 2005-05-30
ANDREW, JOSE 961370847344 HIGH ENCINO 2005-07-07
ANDREW, JOSE 961370847344 LOLA AGENT 2005-08-02
AQUINO, OSCAR 47404727727 AFFAIR PREJUDICE 2005-07-28
AQUINO, OSCAR 474047727727 DRUMS DYNAMITE 2005-06-20
AQUINO, OSCAR 474047727727 EGYPT TENENBAUMS 2005-07-28
AQUINO, OSCAR 474047727727 STREETCAR INTENTIONS 2005-08-01
and so on...
It works even though internal and external SQL WHERE operators are repeated. But that’s not the point – an application that receives query results must track client names to know when to go to the next one. I’ve done this many times and there was always confusion about the results.
How to create a grouped list with GROUP CONCAT
The MySQL GROUP CONCAT function is not new. It unites all non-zero values from the group and returns them as a string with commas separators. In combination with the GROUP BY operator, it allows you to place the grouped data in one line.
Let’s rewrite our code using the GROUP_CONCAT function:
SELECT CONCAT(CU.last_name, ', ', CU.first_name) AS customer,
A.phone,
date(R.rental_date) AS rental_date,
GROUP_CONCAT(F.title) AS titles,
COUNT(*) AS rentals_count
FROM sakila.rental R
LEFT JOIN sakila.inventory I ON R.inventory_id = I.inventory_id
LEFT JOIN sakila.film F ON I.film_id = F.film_id
LEFT JOIN sakila.film_category FC on F.film_id = FC.film_id
LEFT JOIN sakila.category C ON FC.category_id = C.category_id
LEFT JOIN sakila.customer CU ON R.customer_id = CU.customer_id
LEFT JOIN sakila.address A ON CU.address_id = A.address_id
WHERE C.name = "Horror"
GROUP BY R.customer_id
HAVING rentals_count >= 3
ORDER BY customer, title, rental_date DESC;
As you can see, with MySQL GROUP CONCAT the problem of extra data is solved, because you no longer need to filter the results.
The rented movies are listed in the “titles” column:
customer phone rental_date titles rentals_count
———————————————————————————————————————————
ADAM, NATHANIEL 111177206479 2005-08-22 FREDDY STORM,ANALYZE HOOSIERS,STRANGERS GRAFFITI 3
ANDREW, JOSE 961370847344 2005-07-31 EGYPT TENENBAUMS,LOLA AGENT,FIDELITY DEVIL,HIGH ENCINO 4
AQUINO, OSCAR 47404772727 2005-07-28 EGYPT TENENBAUMS,AFFAIR PREJUDICE,STREETCAR INTENTIONS,DRUMS DYNAMITE 4
CARL 20064292617 2005-08-18 BOWFINGER GABLES,RULES HUMAN,YENTL IDAHO,FIDELITY DEVIL 4
BARBEE, CLAYTON 38007794770 2005-05-26 BEHAVIOR RUNAWAY,LOVE SUICIDES,SWARM GOLD 3
and so on...
Besides, one more task has been solved – displaying grouped data in one line. This has a positive impact on the application’s operation, as access to the grouped data is provided by one operation.
This is a fairly simple process using the line break function MySQL GROUP CONCAT, which is implemented in most programming languages.
For example, in PHP this function is called “explode”. As parameters, the function accepts the separator and the string, and returns data as an array. Below is an example of how movie titles can be obtained using the above query:
//resultant set extraction
$res=$mysqli--->query($select_statement);
/Iteration for each line
while ($row = $res->fetch_array(MYSQLI_ASSOC)) {
// this manual separates the titles line
//comma delimited
$titles_array = explode(',', $row['titles']);
// work with an array of names...
}
Another advantage of using GROUP_CONCAT is that the string value can be used as part of the IN operator:
$res_films = $mysqli->query("SELECT * FROM sakila.film WHERE title = IN ($titles_array)");
// working with $res_films...
Conclusion
Do you want to use commas as separators? Want to sort the items? The MySQL GROUP CONCAT function is suitable for both tasks.
GROUP_CONCAT function in SQL
About Enteros
Enteros offers a patented database performance management SaaS platform. It proactively identifies root causes of complex business-impacting database scalability and performance issues across a growing number of clouds, RDBMS, NoSQL, and machine learning database platforms.
The views expressed on this blog are those of the author and do not necessarily reflect the opinions of Enteros Inc. This blog may contain links to the content of third-party sites. By providing such links, Enteros Inc. does not adopt, guarantee, approve, or endorse the information, views, or products available on such sites.
Are you interested in writing for Enteros’ Blog? Please send us a pitch!
RELATED POSTS
Scaling Digital Banking with Confidence: AI SQL and Performance Intelligence by Enteros
- 5 February 2026
- Database Performance Management
Introduction Digital banking has moved from being a competitive differentiator to a baseline expectation. Customers now demand real-time payments, instant account access, personalized financial insights, always-on mobile experiences, and seamless digital onboarding—without delays, downtime, or friction. Behind these experiences lies an increasingly complex technology foundation. Core banking modernization, cloud-native digital platforms, open banking APIs, AI-powered … Continue reading “Scaling Digital Banking with Confidence: AI SQL and Performance Intelligence by Enteros”
Turning Database Performance into Revenue Intelligence: Enteros for US Financial Enterprises
Introduction In the US financial services market, technology performance is no longer just an IT concern—it is a direct driver of revenue, customer trust, and competitive advantage. Banks, fintechs, capital markets firms, insurers, and payments providers all operate in an environment defined by real-time transactions, digital-first customer expectations, regulatory scrutiny, and relentless pressure to improve … Continue reading “Turning Database Performance into Revenue Intelligence: Enteros for US Financial Enterprises”
AI Model–Powered Database Optimization for Real Estate: Performance Management and Cost Attribution with Enteros
- 4 February 2026
- Database Performance Management
Introduction The real estate sector is undergoing a profound digital transformation. Property management platforms, digital leasing systems, smart building technologies, tenant experience apps, AI-driven valuation models, ESG reporting tools, and real-time analytics now form the backbone of modern real estate enterprises. Behind every one of these systems lies a complex database ecosystem—supporting high transaction volumes, … Continue reading “AI Model–Powered Database Optimization for Real Estate: Performance Management and Cost Attribution with Enteros”
Accurate Cost Estimation for Telecom Databases: How Enteros Aligns AIOps and Performance Intelligence
Introduction Telecom organizations are operating at an unprecedented scale. 5G rollouts, digital service platforms, real-time billing systems, subscriber analytics, IoT connectivity, and AI-driven customer engagement have pushed data volumes and transaction complexity to new extremes. Yet while networks continue to modernize, database economics remain poorly understood. Most telecom leaders know their cloud bills are rising. … Continue reading “Accurate Cost Estimation for Telecom Databases: How Enteros Aligns AIOps and Performance Intelligence”