una - especificacion de columna calculada sql server
Combina dos columnas y agrégalas a una nueva columna (3)
¿Revisaste la función de concatenación de cadenas? Algo como:
update table_c set column_a = column_b || column_c
Deberia trabajar. Más here
En PostgreSQL, quiero usar una declaración de SQL para combinar dos columnas y crear una nueva columna de ellas.
Estoy pensando en usar concat(...)
, pero ¿hay una mejor manera?
¿Cuál es la mejor manera de hacer esto?
En general, estoy de acuerdo con el consejo de @ kgrittn . Ve a por ello.
Pero para abordar su pregunta básica sobre concat()
: la nueva función concat()
es útil si necesita tratar con valores nulos , y null no se ha descartado en su pregunta ni en la que se refiere.
Si puede descartar valores nulos, el buen viejo (SQL estándar) operador de concatenación ||
sigue siendo la mejor opción, y la respuesta de @luis está bien:
SELECT col_a || col_b;
Si cualquiera de sus columnas puede ser nula, el resultado sería nulo en ese caso. Podrías defenderte con COALESCE
:
SELECT COALESCE(col_a, '''') || COALESCE(col_b, '''');
Pero eso se vuelve tedioso rápidamente con más argumentos. Ahí es donde entra en concat()
, que nunca devuelve nulo, ni siquiera si todos los argumentos son nulos. concat() :
Los argumentos NULL son ignorados.
SELECT concat(col_a, col_b);
El caso de esquina restante para ambas alternativas es donde todas las columnas de entrada son nulas, en cuyo caso todavía obtenemos una cadena vacía ''''
, pero uno podría querer nulo en su lugar (al menos yo lo haría). Una posible forma:
SELECT CASE
WHEN col_a IS NULL THEN col_b
WHEN col_b IS NULL THEN col_a
ELSE col_a || col_b
END
Esto se vuelve más complejo con más columnas rápidamente. Nuevamente, use concat()
pero agregue un cheque para la condición especial:
SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
ELSE concat(col_a, col_b) END;
¿Como funciona esto?
(col_a, col_b)
es una notación abreviada para una expresión de tipo de fila ROW (col_a, col_b)
. Y un tipo de fila solo es nulo si todas las columnas son nulas. Explicación detallada:
Además, use concat_ws()
para agregar separadores entre elementos ( _ws
.. "con separador").
Una expresión como la de la respuesta de Kevin:
SELECT $1.zipcode || '' - '' || $1.city || '', '' || $1.state;
es tedioso prepararse para valores nulos en PostgreSQL 8.3 (sin concat()
). Una forma (de muchas):
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, '''');
La volatilidad de la función es solo STABLE
Sin embargo, concat_ws()
cuenta que concat()
y concat_ws()
son funciones STABLE
, no IMMUTABLE
porque pueden invocar funciones de salida de tipo de datos (como timestamptz_out
) que dependen de la configuración regional. Explicación por Tom Lane.
Esto prohíbe su uso directo en expresiones de índice. Si sabe que el resultado es realmente inmutable en su caso, puede IMMUTABLE
con un contenedor de funciones IMMUTABLE
. Ejemplo aquí:
No necesita almacenar la columna para referenciarla de esa manera. Prueba esto:
Para configurar:
CREATE TABLE tbl
(zipcode text NOT NULL, city text NOT NULL, state text NOT NULL);
INSERT INTO tbl VALUES (''10954'', ''Nanuet'', ''NY'');
Podemos ver que tenemos "lo correcto":
/pset border 2
SELECT * FROM tbl;
+---------+--------+-------+ | zipcode | city | state | +---------+--------+-------+ | 10954 | Nanuet | NY | +---------+--------+-------+
Ahora agregue una función con el "nombre de columna" deseado que toma el tipo de registro de la tabla como su único parámetro:
CREATE FUNCTION combined(rec tbl)
RETURNS text
LANGUAGE SQL
AS $$
SELECT $1.zipcode || '' - '' || $1.city || '', '' || $1.state;
$$;
Esto crea una función que se puede usar como si fuera una columna de la tabla, siempre que se especifique el nombre o alias de la tabla, así:
SELECT *, tbl.combined FROM tbl;
Que se muestra así:
+---------+--------+-------+--------------------+ | zipcode | city | state | combined | +---------+--------+-------+--------------------+ | 10954 | Nanuet | NY | 10954 - Nanuet, NY | +---------+--------+-------+--------------------+
Esto funciona porque PostgreSQL comprueba primero para una columna real, pero si no se encuentra uno, y el identificador se califica con un nombre de relación o alias, busca una función como la anterior, y la ejecuta con la fila como argumento, regresando el resultado como si fuera una columna. Incluso puede indexar en dicha "columna generada" si desea hacerlo.
Debido a que no está utilizando espacio adicional en cada fila para los datos duplicados, ni disparadores en todas las inserciones y actualizaciones, esto a menudo puede ser más rápido que las alternativas.