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
Why BFSI Leaders Are Turning to Enteros for Database Optimization, AI Ops, and Cloud FinOps Excellence
- 16 April 2026
- Database Performance Management
Introduction The Banking, Financial Services, and Insurance (BFSI) sector is undergoing a massive digital transformation. With the rise of digital banking, real-time payments, fraud detection systems, and AI-driven financial services, organizations are becoming increasingly dependent on high-performance data infrastructure. From managing millions of transactions per second to enabling real-time risk analysis and personalized customer experiences, … Continue reading “Why BFSI Leaders Are Turning to Enteros for Database Optimization, AI Ops, and Cloud FinOps Excellence”
How to Optimize Telecom Sector Growth with Enteros AIOps Platform, Resource Metadata, Hierarchy Metadata, Spot Instances, and RevOps Efficiency
Introduction The telecom sector is at the center of global digital transformation, enabling connectivity for billions of users, businesses, and emerging technologies like IoT, 5G, and edge computing. As demand for high-speed, reliable communication services continues to rise, telecom providers are under immense pressure to scale operations efficiently while maintaining performance and controlling costs. However, … Continue reading “How to Optimize Telecom Sector Growth with Enteros AIOps Platform, Resource Metadata, Hierarchy Metadata, Spot Instances, and RevOps Efficiency”
Who Should Adopt Enteros for Retail Growth Management with AI SQL and Cloud FinOps Efficiency
Introduction The retail sector is evolving at an unprecedented pace, driven by digital transformation, omnichannel experiences, and data-driven decision-making. From global eCommerce giants to mid-sized retail chains, businesses are increasingly relying on cloud infrastructure, databases, and analytics platforms to fuel growth. However, this rapid expansion introduces a fundamental challenge:how to scale efficiently while maintaining performance, … Continue reading “Who Should Adopt Enteros for Retail Growth Management with AI SQL and Cloud FinOps Efficiency”
How to Optimize Technology Sector Growth with Enteros Database Management Platform, Cloud FinOps, and RevOps Efficiency
Introduction The technology sector is at the forefront of innovation, powering digital transformation across industries. From SaaS platforms and cloud-native applications to AI-driven solutions, technology companies are scaling rapidly to meet growing global demand. However, this rapid expansion introduces a critical challenge:how to sustain growth while maintaining high-performance systems, controlling cloud costs, and aligning operations … Continue reading “How to Optimize Technology Sector Growth with Enteros Database Management Platform, Cloud FinOps, and RevOps Efficiency”