PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Combine duas colunas e adicione em uma nova coluna


Geralmente, concordo com o conselho de @kgrittn. Vá em frente.

Mas para resolver sua pergunta básica sobre concat() :A nova função concat() é útil se você precisar lidar com valores nulos - e null não foi descartado na sua pergunta nem na que você se refere.

Se você pode descartar valores nulos, o bom e velho operador de concatenação (padrão SQL) || ainda é a melhor escolha, e a resposta de @luis está bem:
SELECT col_a || col_b;

Se qualquer uma de suas colunas pode ser nula, o resultado seria nulo nesse caso. Você pode defender com COALESCE :
SELECT COALESCE(col_a, '') || COALESCE(col_b, '');

Mas isso fica tedioso rapidamente com mais argumentos. É onde concat() chega, o que nunca retorna nulo, nem mesmo se todos argumentos são nulos. Por documentação:

Os argumentos NULL são ignorados.
SELECT concat(col_a, col_b);

A caixa de canto restante para ambas as alternativas é onde todos as colunas de entrada são nulas nesse caso ainda obtemos uma string vazia '' , mas pode-se querer null (pelo menos eu faria). Uma forma possível:
SELECT CASE
          WHEN col_a IS NULL THEN col_b
          WHEN col_b IS NULL THEN col_a
          ELSE col_a || col_b
       END;

Isso fica mais complexo com mais colunas rapidamente. Novamente, use concat() mas adicione um cheque para a condição especial:
SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
            ELSE concat(col_a, col_b) END;

Como isso funciona?
(col_a, col_b) é uma notação abreviada para uma expressão de tipo de linha ROW (col_a, col_b) . E um tipo de linha só é nulo se todos colunas são nulas. Explicação detalhada:
  • Restrição NOT NULL sobre um conjunto de colunas

Além disso, use concat_ws() para adicionar separadores entre elementos (ws para "com separador").

Uma expressão como a da resposta de Kevin:
SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;

é tedioso preparar valores nulos no PostgreSQL 8.3 (sem concat() ). Uma maneira (de muitas):
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, '');

A volatilidade da função é apenas STABLE


concat() e concat_ws() são STABLE funções, não IMMUTABLE porque eles podem invocar funções de saída de tipo de dados (como timestamptz_out ) que dependem das configurações de localidade.
Explicação de Tom Lane.

Isso proíbe seu uso direto em expressões de índice. Se você sabe que o resultado é realmente imutável no seu caso, você pode contornar isso com um IMMUTABLE invólucro de função. Exemplo aqui:
  • O PostgreSQL suporta agrupamentos "insensíveis ao acento"?