Как объединить строки в SQL
| СУБД | Склеить столбцы |
|---|---|
| SQLite, PostgreSQL | first_name || ' ' || last_name |
| MySQL, MariaDB | CONCAT(first_name, ' ', last_name) |
| PostgreSQL, SQLite 3.44 и новее | concat(first_name, ' ', last_name) тоже работает |
CREATE TABLE people (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
middle TEXT,
city TEXT
);
INSERT INTO people (first_name, last_name, middle, city) VALUES
('Анна', 'Ковалёва', 'Петровна', 'Минск'),
('Борис', 'Ивашкевич', NULL, 'Гомель'),
('Вера', 'Лис', 'Олеговна', 'Минск');
SELECT first_name || ' ' || last_name AS full_name FROM people;| full_name |
|---|
| Анна Ковалёва |
| Борис Ивашкевич |
| Вера Лис |
В MySQL || по умолчанию означает «или» (как OR), а не склейку: 'а' || 'б' даст 0. Там пишите CONCAT.
Склейка и NULL
У Бориса нет отчества, и склейка через || превращает всю строку в NULL:
SELECT last_name || ' ' || first_name || ' ' || middle AS fio FROM people;| fio |
|---|
| Ковалёва Анна Петровна |
| NULL |
| Лис Вера Олеговна |
Исправить можно так: COALESCE подставит пустую строку вместо NULL, а пробел добавится только вместе с отчеством:
SELECT last_name || ' ' || first_name || COALESCE(' ' || middle, '') AS fio FROM people;| fio |
|---|
| Ковалёва Анна Петровна |
| Ивашкевич Борис |
| Лис Вера Олеговна |
Проще — concat_ws (with separator — «с разделителем»): первый аргумент — разделитель, NULL пропускаются. Есть в MySQL, PostgreSQL и SQLite 3.44 и новее:
SELECT concat_ws(' ', last_name, first_name, middle) AS fio FROM people;С функцией CONCAT по-разному: в MySQL она возвращает NULL, если хоть один аргумент NULL, а в PostgreSQL и SQLite просто пропускает такие аргументы.
Склейка с числами
Числа превращаются в текст сами: 'Цена: ' || 25 || ' руб.' даст Цена: 25 руб.. Но в SQLite || выполняется раньше умножения, и 'Итого: ' || 10 * 2.5 даст не «Итого: 25.0», а 0.0. Вычисления берите в скобки: 'Итого: ' || (10 * 2.5).
Значения многих строк — в одну
Все имена каждого города через запятую:
SELECT city, group_concat(first_name, ', ') AS names
FROM people
GROUP BY city
ORDER BY city;| city | names |
|---|---|
| Гомель | Борис |
| Минск | Анна, Вера |
| СУБД | Функция |
|---|---|
| SQLite | group_concat(first_name, ', '), с версии 3.44 также string_agg(first_name, ', ') |
| MySQL, MariaDB | GROUP_CONCAT(first_name SEPARATOR ', ') |
| PostgreSQL | string_agg(first_name, ', ') |
| SQL Server 2017 и новее | STRING_AGG(first_name, ', ') |
Порядок внутри строки не гарантирован, если его не задать: GROUP_CONCAT(first_name ORDER BY first_name SEPARATOR ', ') в MySQL, string_agg(first_name, ', ' ORDER BY first_name) в PostgreSQL и SQLite 3.44 и новее.
MySQL обрезает результат GROUP_CONCAT до 1024 байт без ошибки — только с предупреждением. Для длинных списков увеличьте предел: SET SESSION group_concat_max_len = 100000;.