Función COALESCE en TSQL

109

¿Alguien puede explicar cómo funciona la función COALESCE en TSQL? La sintaxis es la siguiente

COALESCE (x, y)

El documento de MSDN sobre esta función es bastante vago

Lloyd Banks
fuente

Respuestas:

74

Me han dicho que COALESCE es menos costoso que ISNULL, pero las investigaciones no lo indican. ISNULL solo toma dos parámetros, el campo que se evalúa como NULL y el resultado que desea si se evalúa como NULL. COALESCE tomará cualquier número de parámetros y devolverá el primer valor encontrado que no sea NULL.

Hay una descripción mucho más completa de los detalles aquí http://www.mssqltips.com/sqlservertip/2689/deciding-between-coalesce-and-isnull-in-sql-server/

Bill Melius
fuente
6
Tenga cuidado con el uso ISNULL, no es estándar, menos flexible, leí que siempre devolverá el tipo de datos del primer argumento y no el tipo de datos del valor devuelto como lo COALESCEhace.
piñón
215

No estoy seguro de por qué cree que la documentación es vaga.

Simplemente revisa todos los parámetros uno por uno y devuelve el primero que es NOT NULL.

COALESCE(NULL, NULL, NULL, 1, 2, 3)
=> 1


COALESCE(1, 2, 3, 4, 5, NULL)
=> 1


COALESCE(NULL, NULL, NULL, 3, 2, NULL)
=> 3


COALESCE(6, 5, 4, 3, 2, NULL)
=> 6


COALESCE(NULL, NULL, NULL, NULL, NULL, NULL)
=> NULL

Acepta prácticamente cualquier cantidad de parámetros, pero deben ser del mismo tipo de datos. (Si no son del mismo tipo de datos, se convierten implícitamente en un tipo de datos apropiado usando el orden de precedencia del tipo de datos ).

Es como ISNULL()pero para múltiples parámetros, en lugar de solo dos.

También es ANSI-SQL, donde-como ISNULL()no.

MatBailie
fuente
4
+1 Para su explicación sobre la prioridad de los tipos de datos. Sin ISNULLembargo, creo que devuelve un valor con el mismo tipo de datos que el primer parámetro
Lamak
5
Su último ejemplo de código debería dar el error 'Al menos uno de los argumentos de COALESCE debe ser un NULL escrito' Fuente: sql-server-performance.com/2007/…
maqk
2
La documentación dice mucho al mismo tiempo que logra proporcionar un valor casi nulo. Los buenos documentos proporcionan un ejemplo sencillo con un resultado sencillo. Coalesce pasa inmediatamente a expressionscomparaciones con CASE, comparaciones con ISNULL y, finalmente, a un ejemplo sin resultado. Luego, un ejemplo demasiado complejo con demasiados detalles. Cuando todo lo que necesitamos es esta respuesta con 5-6 líneas de WTF, esto es y lo hace.
P.Brian.Mackey
1
Detalles de la precedencia del tipo
IsmailS
18

Así es como veo a COALESCE ... y espero que tenga sentido ...

En una forma simplista….

Coalesce (FieldName, 'Vacío')

Entonces esto se traduce en… Si "FieldName" es NULL, complete el valor del campo con la palabra "EMPTY".

Ahora para múltiples valores ...

Coalesce (FieldName1, FieldName2, Value2, Value3)

Si el valor en Fieldname1 es nulo, rellénelo con el valor en Fieldname2, si FieldName2 es NULL, rellénelo con Value2, etc.

Esta pieza de código de prueba para la base de datos de muestra AdventureWorks2012 funciona perfectamente y ofrece una buena explicación visual de cómo funciona COALESCE :

SELECT Name, Class, Color, ProductNumber,
COALESCE(Class, Color, ProductNumber) AS FirstNotNull
FROM Production.Product
John Waclawski
fuente
4

Hay mucho más para fusionar que solo un reemplazo para ISNULL. Estoy completamente de acuerdo en que la "documentación" oficial de coalesce es vaga e inútil. Este artículo ayuda mucho. http://www.mssqltips.com/sqlservertip/1521/the-many-uses-of-coalesce-in-sql-server/

CindyPsych
fuente
3
Ese artículo al que vinculó es extremadamente engañoso (como lo señalaron varias personas, incluido el autor, en la sección de comentarios). Todos los trucos ingeniosos que destaca se pueden hacer TODOS usando ISNULL en lugar de fusionar.
Hobo Spider
3

Aquí hay una consulta simple que contiene coalesce:

select * from person where coalesce(addressId, ContactId) is null.

Devolverá las personas donde tanto addressId como contactId son nulos.

función de unión

  • toma al menos dos argumentos.
  • los argumentos deben ser de tipo entero.
  • devuelve el primer argumento no nulo.

p.ej

  • coalesce (nulo, 1, 2, 3) devolverá 1.
  • coalesce (nulo, nulo) devolverá nulo.
Neeraj Bansal
fuente
1

La definición más simple de la función Coalesce () podría ser:

La función Coalesce () evalúa todos los argumentos pasados ​​y luego devuelve el valor de la primera instancia del argumento que no se evaluó como NULL.

Nota: evalúa TODOS los parámetros, es decir, no omite la evaluación de los argumentos en el lado derecho del parámetro devuelto / NOT NULL.

Sintaxis:

Coalesce(arg1, arg2, argN...)

Atención : además de los argumentos que se evalúan como NULL, todos los demás argumentos (NOT-NULL) deben ser del mismo tipo de datos o deben ser de tipos coincidentes (que pueden "autoconvertirse implícitamente" en un tipo de datos compatible), consulte los ejemplos abajo:

PRINT COALESCE(NULL, ('str-'+'1'), 'x')  --returns 'str-1, works as all args (excluding NULLs) are of same VARCHAR type.
--PRINT COALESCE(NULL, 'text', '3', 3)    --ERROR: passed args are NOT matching type / can't be implicitly converted.
PRINT COALESCE(NULL, 3, 7.0/2, 1.99)      --returns 3.0, works fine as implicit conversion into FLOAT type takes place.
PRINT COALESCE(NULL, '1995-01-31', 'str') --returns '2018-11-16', works fine as implicit conversion into VARCHAR occurs.

DECLARE @dt DATE = getdate()
PRINT COALESCE(NULL, @dt, '1995-01-31')  --returns today's date, works fine as implicit conversion into DATE type occurs.

--DATE comes before VARCHAR (works):
PRINT COALESCE(NULL, @dt, 'str')      --returns '2018-11-16', works fine as implicit conversion of Date into VARCHAR occurs.

--VARCHAR comes before DATE (does NOT work):
PRINT COALESCE(NULL, 'str', @dt)      --ERROR: passed args are NOT matching type, can't auto-cast 'str' into Date type.

HTH

Eddie Kumar
fuente
0
declare @store table (store_id varchar(300))
insert into @store 
values ('aa'),('bb'),('cc')
declare @str varchar (4000)
select @str = concat(@str+',',store_id) from @store
select @str
Xiao
fuente
1
Encontré que este es mucho más simple.
Xiao