PostgreSQL 9.0 або новішої версії:
Останні версії Postgres (з кінця 2010 року) мають string_agg(expression, delimiter)
функцію, яка виконуватиме саме те, що було запропоновано, навіть дозволяючи вказати рядок роздільника:
SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;
Postgres 9.0 також додав можливість задавати ORDER BY
пункт у будь-якому сукупному виразі ; в іншому випадку порядок не визначено. Тепер ви можете написати:
SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;
Або справді:
SELECT string_agg(actor_name, ', ' ORDER BY first_appearance)
PostgreSQL 8.4 або новішої версії:
PostgreSQL 8.4 (у 2009 році) запровадив функцію сукупності,array_agg(expression)
яка об'єднує значення в масив. Потім array_to_string()
можна використовувати бажаний результат:
SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM mytable
GROUP BY company_id;
string_agg
для версій до 8.4:
У разі, якщо хтось стикається з цим, шукаючи сукупність сумісності для баз даних до 9.0, можливо реалізувати все, string_agg
крім ORDER BY
пункту.
Отже, із нижченаведеним визначенням це має працювати так само, як у 9.x БД Postgres:
SELECT string_agg(name, '; ') AS semi_colon_separated_names FROM things;
Але це буде синтаксична помилка:
SELECT string_agg(name, '; ' ORDER BY name) AS semi_colon_separated_names FROM things;
--> ERROR: syntax error at or near "ORDER"
Тестовано на PostgreSQL 8.3.
CREATE FUNCTION string_agg_transfn(text, text, text)
RETURNS text AS
$$
BEGIN
IF $1 IS NULL THEN
RETURN $2;
ELSE
RETURN $1 || $3 || $2;
END IF;
END;
$$
LANGUAGE plpgsql IMMUTABLE
COST 1;
CREATE AGGREGATE string_agg(text, text) (
SFUNC=string_agg_transfn,
STYPE=text
);
Спеціальні варіанти (усі версії Postgres)
До 9.0 не було вбудованої функції сукупності для об'єднання рядків. Найпростіша спеціальна реалізація ( запропонована Вайдою Габо у цій публікації списку розсилки , серед багатьох інших) - це використання вбудованої textcat
функції (яка лежить позаду ||
оператора):
CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);
Ось CREATE AGGREGATE
документація.
Це просто склеює всі пасма разом, без поділу. Для того, щоб вставити "", вставлений між ними, не маючи його в кінці, ви можете зробити свою власну функцію конкатенації та замінити її на "текстовий кот" вище. Ось один я зібрав і випробував 8.3.12:
CREATE FUNCTION commacat(acc text, instr text) RETURNS text AS $$
BEGIN
IF acc IS NULL OR acc = '' THEN
RETURN instr;
ELSE
RETURN acc || ', ' || instr;
END IF;
END;
$$ LANGUAGE plpgsql;
Ця версія виведе кому, навіть якщо значення в рядку є нульовим або порожнім, тож ви отримаєте такий вихід:
a, b, c, , e, , g
Якщо ви бажаєте видалити зайві коми, щоб вивести це:
a, b, c, e, g
Потім додайте ELSIF
чек до такої функції:
CREATE FUNCTION commacat_ignore_nulls(acc text, instr text) RETURNS text AS $$
BEGIN
IF acc IS NULL OR acc = '' THEN
RETURN instr;
ELSIF instr IS NULL OR instr = '' THEN
RETURN acc;
ELSE
RETURN acc || ', ' || instr;
END IF;
END;
$$ LANGUAGE plpgsql;