sqlcmd.net validated sql reference
advanced aggregation MySQL MariaDB SQL Server PostgreSQL SQLite

Concatenate Values Within A Group

Aggregate multiple string values from grouped rows into a single delimited string.

Docker-validated Not currently validation-green

List each customer's ordered products as a single string

Each customer's products are sorted alphabetically within the group before being joined. Alice's two products become 'Keyboard, Mouse'; Bob's become 'Keyboard, Monitor'. Carol has a single product so no separator appears.

MySQL MariaDB
Engine-specific syntax
Setup
CREATE TABLE orders (id INT, customer VARCHAR(50), product VARCHAR(50));

INSERT INTO
  orders (id, customer, product)
VALUES
  (1, 'Alice', 'Keyboard'),
  (2, 'Alice', 'Mouse'),
  (3, 'Bob', 'Monitor'),
  (4, 'Bob', 'Keyboard'),
  (5, 'Carol', 'Mouse');
SQL
SELECT
  customer,
  GROUP_CONCAT (
    product
    ORDER BY
      product SEPARATOR ', '
  ) AS products
FROM
  orders
GROUP BY
  customer
ORDER BY
  customer;
customerproducts
AliceKeyboard, Mouse
BobKeyboard, Monitor
CarolMouse
SQL Server
Engine-specific syntax
Setup
CREATE TABLE orders (id INT, customer VARCHAR(50), product VARCHAR(50));

INSERT INTO
  orders (id, customer, product)
VALUES
  (1, 'Alice', 'Keyboard'),
  (2, 'Alice', 'Mouse'),
  (3, 'Bob', 'Monitor'),
  (4, 'Bob', 'Keyboard'),
  (5, 'Carol', 'Mouse');
SQL
SELECT
  customer,
  STRING_AGG (product, ', ') WITHIN GROUP (
    ORDER BY
      product
  ) AS products
FROM
  orders
GROUP BY
  customer
ORDER BY
  customer;
customerproducts
AliceKeyboard, Mouse
BobKeyboard, Monitor
CarolMouse
PostgreSQL
Engine-specific syntax
Setup
CREATE TABLE orders (id INT, customer VARCHAR(50), product VARCHAR(50));

INSERT INTO
  orders (id, customer, product)
VALUES
  (1, 'Alice', 'Keyboard'),
  (2, 'Alice', 'Mouse'),
  (3, 'Bob', 'Monitor'),
  (4, 'Bob', 'Keyboard'),
  (5, 'Carol', 'Mouse');
SQL
SELECT
  customer,
  STRING_AGG (
    product,
    ', '
    ORDER BY
      product
  ) AS products
FROM
  orders
GROUP BY
  customer
ORDER BY
  customer;
customerproducts
AliceKeyboard, Mouse
BobKeyboard, Monitor
CarolMouse
SQLite
Engine-specific syntax
Setup
CREATE TABLE orders (id INT, customer VARCHAR(50), product VARCHAR(50));

INSERT INTO
  orders (id, customer, product)
VALUES
  (1, 'Alice', 'Keyboard'),
  (2, 'Alice', 'Mouse'),
  (3, 'Bob', 'Monitor'),
  (4, 'Bob', 'Keyboard'),
  (5, 'Carol', 'Mouse');
SQL
SELECT
  customer,
  GROUP_CONCAT (product, ', ') AS products
FROM
  (
    SELECT
      customer,
      product
    FROM
      orders
    ORDER BY
      customer,
      product
  ) sub
GROUP BY
  customer
ORDER BY
  customer;
customerproducts
AliceKeyboard, Mouse
BobKeyboard, Monitor
CarolMouse

MySQL and MariaDB use GROUP_CONCAT; PostgreSQL and SQL Server use STRING_AGG. Results are identical.

Where this command helps.

  • building a comma-separated list of items per customer or category
  • collapsing a one-to-many relationship into a single readable column

What the command is doing.

String aggregation collapses multiple rows into a comma-separated list within a GROUP BY. MySQL and MariaDB use GROUP_CONCAT, while PostgreSQL and SQL Server use STRING_AGG. Both support ordering the values within each group before concatenation.