Объедините два столбца и добавьте в один новый столбец.

В PostgreSQL я хочу использовать оператор SQL для объединения двух столбцов и создания из них нового столбца.

Я думаю об использовании concat(...), но есть ли лучший способ?
Какой лучший способ сделать это?

3 ответа

Решение

В общем, я согласен с советом @kgrittn. Действуй.

Но чтобы ответить на ваш основной вопрос о concat(): Новая функция concat() полезно, если вам нужно иметь дело со значениями NULL - и NULL не исключено ни в вашем вопросе, ни в том, на который вы ссылаетесь.

Если вы можете исключить нулевые значения, старый добрый (стандарт SQL) оператор конкатенации || все еще лучший выбор, и ответ @luis очень хорош:

SELECT col_a || col_b;

Если любой из ваших столбцов может быть нулевым, в этом случае результат будет нулевым. Вы могли бы защитить с COALESCE:

SELECT COALESCE(col_a, '') || COALESCE(col_b, '');

Но это быстро становится утомительным с большим количеством аргументов. Это где concat() приходит, который никогда не возвращает ноль, даже если все аргументы нулевые. По документации:

Пустые аргументы игнорируются.

SELECT concat(col_a, col_b);

Оставшийся угловой случай для обеих альтернатив - это когда все входные столбцы равны нулю, и в этом случае мы все еще получаем пустую строку '', но можно вместо этого хотеть ноль (по крайней мере, я бы хотел). Один из возможных способов:

SELECT CASE
          WHEN col_a IS NULL THEN col_b
          WHEN col_b IS NULL THEN col_a
          ELSE col_a || col_b
       END

Это становится более сложным с большим количеством столбцов быстро. Опять же, используйте concat() но добавьте проверку для специального условия:

SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
            ELSE concat(col_a, col_b) END;

Как это работает?
(col_a, col_b) является сокращенной записью для выражения типа строки ROW (col_a, col_b), И тип строки является только нулевым, если все столбцы являются нулевыми. Детальное объяснение:

Также используйте concat_ws() добавить разделители между элементами (_ws.. "с разделителем").


Выражение, похожее на выражение в ответе Кевина:

SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;

утомительно готовить нулевые значения в PostgreSQL 8.3 (без concat()). Один из способов (из многих):

SELECT COALESCE(
         CASE
          WHEN $1.zipcode IS NULL THEN $1.city
          WHEN $1.city IS NULL THEN $1.zipcode
          ELSE $1.zipcode || ' - ' || $1.city
         END, '')
       || COALESCE(', ' || $1.state, '');

Функция волатильности только STABLE

Обратите внимание, однако, что concat() а также concat_ws() являются STABLE функции, а не IMMUTABLE потому что они могут вызывать функции вывода типа данных (например, timestamptz_out), которые зависят от настроек локали. Объяснение Тома Лейна.

Это запрещает их прямое использование в выражениях индекса. Если вы знаете, что результат на самом деле является неизменным в вашем случае, вы можете обойти это с помощью IMMUTABLE функциональная обертка. Пример здесь:

Вам не нужно хранить столбец, чтобы ссылаться на него таким образом. Попробуй это:

Установить:

CREATE TABLE tbl
  (zipcode text NOT NULL, city text NOT NULL, state text NOT NULL);
INSERT INTO tbl VALUES ('10954', 'Nanuet', 'NY');

Мы можем видеть, что у нас есть "правильные вещи":

\pset border 2
SELECT * FROM tbl;
+ --------- + -------- + ------- +
| почтовый индекс | город | состояние |
+---------+--------+-------+
| 10954   | Нануэт | Нью-Йорк |
+ --------- + -------- + ------- +

Теперь добавьте функцию с нужным "именем столбца", которая принимает тип записи таблицы в качестве единственного параметра:

CREATE FUNCTION combined(rec tbl)
  RETURNS text
  LANGUAGE SQL
AS $$
  SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;
$$;

Это создает функцию, которую можно использовать, как если бы это был столбец таблицы, если указано имя таблицы или псевдоним, например:

SELECT *, tbl.combined FROM tbl;

Который отображается так:

+ --------- + -------- + ------- + -------------------- +
| почтовый индекс | город | состояние | комбинированный |
+---------+--------+-------+--------------------+
| 10954   | Нануэт | Нью-Йорк | 10954 - Nanuet, NY |
+---------+--------+-------+--------------------+

Это работает, потому что PostgreSQL сначала проверяет фактический столбец, но если он не найден, а идентификатор квалифицируется именем отношения или псевдонимом, он ищет функцию, подобную приведенной выше, и запускает ее со строкой в ​​качестве аргумента, возвращая результат, как если бы это был столбец. Вы можете даже индексировать такой "сгенерированный столбец", если хотите.

Поскольку вы не используете дополнительное пространство в каждой строке для дублированных данных или запускаете триггеры на всех вставках и обновлениях, это часто может быть быстрее, чем альтернативы.

Вы проверяли функцию конкатенации строк? Что-то вроде:

update table_c set column_a = column_b || column_c 

должно сработать. Больше здесь

Другие вопросы по тегам