sábado, 3 de octubre de 2015

CASE WHEN en SQL Server


Consultas  SQL SERVER adaptadas al usuario

Muchas veces el administrador de Base de datos  SQL Server recibe el encargo de una consulta normal y corriente por  una persona que no conoce el diseño interno de la base de datos. El administrador realiza su consulta.

select Nombre_Campo, Nombre_Campo2, Nombre_Campo3 from propietario.Nombre_tabla where Nombre_Campo =  'Condición'

Y se encuentra con el resultado:
SELECT adpatada al usuario CASE WHEN

Copia el resultado en un Excel, se lo envía al usuario (que suele ser el jefe) y se lleva una bronca monumental por hacer su trabajo.

El problema es que el jefe no entiende que significa el 1 del campo 2 ni el 8 del campo 3 así que le pide que se lo traduzca. Un mal administrador buscaría la tabla asociada con los significados de cada número y lo traduciría a mano directamente en Excel.

Un buen administrador buscaría esas mismas tablas y las enlazaría en la SELECT con un INNER JOINT  de este modo

SELECT        PROPIETARIO.Nombre_Tabla_Datos.intError, PROPIETARIO.Nombre_Tabla_Referencias.strDescripcion

FROM            PROPIETARIO.Nombre_Tabla_Referencias INNER JOIN

                         PROPIETARIO.Nombre_Tabla_Datos ON PROPIETARIO.Nombre_Tabla_Referencias = PROPIETARIO.Nombre_Tabla_Datos

Aquí el resultado ya será comprensible por el usuario.
CASE WHEN en SQL Server

 Pero hay un caso aun peor. Es posible que la base de datos no haya sido diseñada por nosotros y por tanto que no cumpla las formas normales  y por tanto podemos encontrarnos con valores de campos que no tienen la tabla de traducción correspondiente. En este caso tampoco es necesario cambiar manualmente el Excel para traducir los valores, se pueden traducir directamente en la Consulta utilizando CASE WHEN  del siguiente modo:


SELECT  PROPIETARIO.Nombre_Tabla.Nombre_Campo1,                               

                                CASE WHEN PROPIETARIO.Nombre_Tabla.Campo_Estado = 1

                                THEN 'CASO_1'

                                ELSE 'CASO_2'
                                END AS NOMBRE_COLUMNA,
                                PROPIETARIO.Nombre_Tabla.Nombre_Campo_N
FROM   PROPIETARIO.Nombre_Tabla

Si el campo tiene múltiples opciones tenemos una versión un poco más compleja:

SELECT  PROPIETARIO.Nombre_Tabla.Nombre_Campo1,
CASE
                                 WHEN PROPIETARIO.Nombre_Tabla.Campo_Estado  = 1    THEN 'CASO_1'
                                 WHEN PROPIETARIO.Nombre_Tabla.Campo_Estado  = 2    THEN 'CASO_2'
                                ELSE 'CASO_3'
                                END AS NOMBRE_COLUMNA,
PROPIETARIO.Nombre_Tabla.Nombre_Campo_N
FROM   PROPIETARIO.Nombre_Tabla

Este tipo de consultas no se realizarán solamente si la base de datos está mal diseñada, hay múltiples casos en los que es necesario traducir condiciones complejas, por ejemplo pueden pedirnos que una columna muestre una S si una consulta diferente a la que estamos implementando cumple unas condiciones determinadas y un a N si no las cumple. En general se pueden complicar mucho los casos pero siempre siguiendo el mismo patrón, el código siguiente muestra el caso comentado.

SELECT  PROPIETARIO.Nombre_Tabla.Nombre_Campo1,
     CASE WHEN
          EXISTS
                (
                     SELECT *
                     FROM
                          PROPIETARIO.Nombre_Tabla2
                     WHERE PROPIETARIO.Nombre_Tabla2.Nombre_Campo1 = 1  
                )
                    THEN 'S'
          ELSE 'N'
     END AS NOMBRE_CAMPO2,
PROPIETARIO.Nombre_Tabla.Nombre_Campo_N
FROM   PROPIETARIO.Nombre_Tabla

En este caso se ha insertado una subselect dentro las condiciones para mostrar el campo.
O también se pueden insertar otro tipo de funciones (por ejemplo las matemáticas)  y combinar en ellos varios campos de varias tablas.

SELECT  PROPIETARIO.Nombre_Tabla.Nombre_Campo1,                          
                               PROPIETARIO.Nombre_Tabla.Nombre_Campo2=SUM(ISNULL((-((CONVERT(DECIMAL,(SUBSTRING(PROPIETARIO.Nombre_Tabla.Nombre_Campo2,10,1))))*2 - 1)) * PROPIETARIO.Nombre_Tabla2.CampoN,0)),
PROPIETARIO.Nombre_Tabla_Campo_N
FROM   PROPIETARIO.Nombre_Tabla

Como podemos ver hay multitud de posibilidades para insertar entre los campos de una consulta SELECT normal y corriente y esto puede complicarla mucho desde el punto de vista de un primer vistazo pero simplificar los resultados mostrados de cara al usuario final, si tenemos en perspectiva la separación de cada campo la SELECT por muy compleja que parezca no dejará de ser una consulta normal y corriente.






1 comentario: