domingo, 28 de diciembre de 2014

CONSULTA SELECT 1

Buenos Días.

Hoy estaremos empezando con una serie de artículo, del famoso SELECT *, mejor dicho, cláusula de selección para SQL, una forma de obtener RecordSets.

Dicha sentencia que parece muy simple, en realidad puede tener altísimos niveles de complejidad, dependiendo del tipo de resultado que se necesita obtener, dichos resultados pueden ser, tablas planas, agrupamientos, cruces, pivotes, etc... Iremos viendo todos estos en su debido artículo. Hoy empezaremos con el más básico, y algunos TIPS para no tan básicos.

****************
NOTA:
Nuestra base de datos de trabajo será la base de datos: AdventureWorks2008R2, sobre Microsoft SQL 2008R2, y utilizando como IDE el Microsoft Server Management 2008. En caso de no tener nada de esto instalado, por favor entrar en Guia de Instalación Básica, para tener todo lo necesario y luego proseguir.
*****************

Empecemos!!! :)

La consulta SELECT se utiliza para indicar a la base de datos que nos devuelva cierta información en un objeto que almacena registros (RecordSet), esto es sumamente importante, porque si tenemos código que necesita de devoluciones de la base de datos, la misma puede obtenerla por medio de RecordSet o variables de retorno tipo OUTPUT (aunque esto lo dejaremos para mucho más adelante), Sigamos.

Tal cual lo comentado la sentencia SELECT obtiene un RecordSet, y la estructura es la siguiente.

SELECT [CAMPOS/VALORES] FROM [NOMBRE_TABLA]

Por lo general, y en el 99% de los casos, utilizaremos los campos de cierta tabla que necesitemos, aunque podemos tener excepciones!, en el cual necesitemos incorporar valores específicos a la consulta SELECT, no nos mareemos, un ejemplo vale más que mil palabras, vamos a lo práctico.

Sabiendo que ya estamos trabajando dentro de la base de datos AdventureWorks, disfrutaremos de unas sentencias. Antes que nada, voy a aclarar que mostraré las sentencias en formato PURISTA, eso significa no obviando cierta sintaxis que el motor de base de datos sabe reconocer y por otra parte la base de datos adventureWorks utiliza la notación de SCHEMA.TABLE, esta notación la utilizan muy pocos sistemas (la mayoría utiliza un único esquema DBO) y es una buena práctica para trabajar con las tablas (no es la única).

Primer Ejemplo:
SELECT 
  PE.BusinessEntityID,
  PE.PersonType,
  PE.NameStyle,
  PE.Title,
  PE.FirstName,
  PE.MiddleName,
  PE.LastName,
  PE.Suffix,
  PE.EmailPromotion,
  PE.AdditionalContactInfo,
  PE.Demographics,
  PE.rowguid,
  PE.ModifiedDate 
   FROM [PERSON].[PERSON] AS PE

Como podemos apreciar, es una consulta muy muy sencilla, donde la estructura anterior se cumple, se encuentran los campos escritos en la cláusula SELECT y estos vienen del esquema PERSON tabla PERSON = PERSON.PERSON.

De la anterior consulta uno solo puede utilizar los campos que necesita, ya que estos se encuentra declarados, una forma práctica de instanciar todos los campos sin la necesidad de escribirlos todos, es de la siguiente forma.
SELECT * FROM [PERSON].[PERSON]

De esta manera el motor de SQL reconoce que antes de ejecutar la consulta en el motor de base de datos, tiene que instanciar todas las columnas (reconoce la estructura), esto reduce en forma insignificante la performance debido a que el motor antes de disparar la consulta la tiene que interpretar, y agrega un paso más al plan de ejecución. En caso de ser una consulta que se ejecuta un par de centenas de veces por minuto la pérdida de rendimiento no es significativa, pero en caso de ser una consulta que se ejecute miles de veces por segundo, la merma es para tenerla en cuenta (sobre todo si hay campos que se nos devuelven y son innecesarios). Sepamos que cuanto más optimicemos las consultas de un sistema, mejoraremos el rendimiento del motor de base de datos y tendremos mejores resultados en nuestros sistemas.

Bien, sepamos que cuando utilizamos el *, no tenemos forma de excluir en la sentencia los campos que no queremos, mostrando siempre todos.

Siguiendo con lo anterior, realizaremos algo simple y más practico, supongamos que queremos un listado de todos los nombres que estuvieron en AdventureWorks, con los siguientes campos, Primer Nombre, Segundo Nombre, Apellido.

Para ello usamos la siguiente consulta:
SELECT 
  PE.FirstName,
  PE.MiddleName,
  PE.LastName
   FROM [PERSON].[PERSON] AS PE

Realizado esto, supongamos que queremos ordenarlos por primer nombre ASCENDENTE (ASC), también podemos realizarlo en forma DESCENDENTE (DESC)

Nos queda de la siguiente forma:
SELECT 
  PE.FirstName,
  PE.MiddleName,
  PE.LastName
   FROM [PERSON].[PERSON] AS PE
ORDER BY 
  PE.FirstName ASC

En esta lista vamos a tener nombres que se nos repiten, por lo tanto queremos solamente los distintos, utilizamos el predicado DISTINCT:
SELECT DISTINCT
  PE.FirstName,
  PE.MiddleName,
  PE.LastName
   FROM [PERSON].[PERSON] AS PE
ORDER BY 
  PE.FirstName ASC

Supongamos que en el informe que nos piden, necesitan que el formato sea de la siguiente manera: Apellido, primer nombre segundo nombre.

La forma de realizarlo es la siguiente:
SELECT DISTINCT
  ISNULL(PE.LastName, '') + ', ' + ISNULL(PE.FirstName, '') + ' ' + ISNULL(PE.MiddleName, '') AS NOMBRE
   FROM [PERSON].[PERSON] AS PE
ORDER BY 
  NOMBRE ASC

¿¿¿PERO QUE PASO ACA???, Aparecen cosas nuevas, y aparte en el ORDER BY tenemos el nombre de un ALIAS, y no el de un campo de la tabla. Acá vemos como a veces hacer algo que parece simple, requiere de cierta técnica para realizarlo correctamente. Empecemos a aclarar las aguas!!!

En primer punto estamos usando el operador '+', este operador se comporta de diferentes maneras dependiendo los tipos de campos afectados, por otra parte, los tipos de campos deben de ser del mismo tipo, para solucionar inconvenientes en caso de que no sean del mismo tipo, siempre podemos castear pero eso ya lo veremos más adelante con detalle, por lo pronto sabemos que es de la siguiente manera.

SELECT TEXTO1 + ' ' + TEXTO2 = TEXTO1 TEXTO2
SELECT NUMERO>1 + NUMERO>2 = NUMERO>3

En lo anterior se resume la forma, se puede apreciar que en el caso de texto incorporo un literal de espacio, para que no quede todo junto, caso contrario queda TEXTO1TEXTO2.

Bien, con esto anterior sabemos que podemos concatenar textos, o realizar operaciones con los números, para el caso de los números se soportan todas los operadores matemáticos por otra parte el motor de SQL contiene también funciones matemáticas avanzadas.

Sigamos con lo que sigue, ¿porque utilizamos ISNULL en los campos?, Acá es importante entender el concepto de lo que es NULL. Cuando listamos la tabla anteriormente se podrá haber visto que el campo NULL aparte de decir esta palabra, estaba en otro color, otros IDE ponen el NULL en itálica, esto es así porque en realidad NULL es un estado adicional en un campo, que significa NO INICIALIZADO o VACIO.

Por ejemplo, un campo tipo BIT en una base de datos se puede trabajar con tres valores, ¿cómo es eso?, de la siguiente forma. El campo puede tener el valor 0, el valor 1 y el valor NULL, y con cada una podemos realizar operaciones diferentes. ¿Entonces porque estoy utilizando el ISNULL en la concatenación?, veamos en forma ejemplificada.

TEXTO1 + ' ' + TEXTO2 + ' ' + TEXTO3 = TEXTO1 TEXTO2 TEXTO3
TEXTO1 + ' ' + NULL + ' ' + TEXTO3 = NULL

Como se puede apreciar en el ejemplo anterior, si cualquiera de los campos que se está concatenando se encuentra NULL, toda la cadena será NULL y es por eso que utilizamos ese condicional en este caso, ya que en el algunos el campo middlename se encuentra NULL, al pasar esto, la información que obtendremos será incompleta.
La función del sistema ISNULL necesita de dos argumentos.

ISNULL (EXPRESION_A_VERIFICAR , VALOR_DE_REEMPLAZO)

Donde sí, EXPRESION_A_VERIFICAR es NULO, entonces este se reemplaza con VALOR_DE_REEMPLAZO, en nuestro ejemplo anterior, se reemplaza con un literal vacío ''. Aclaro que VALOR_DE_REEMPLAZO puede ser, una sub-consulta, variables,  funciones, etc... Pero eso lo iremos viendo más adelante.

Entonces analizado esto, nos quedan dos cosas más, el AS NOMBRE. Esto es, a cada campo, o campo creado de un literal, o campo concatenado, etc... Podemos utilizar un ALIAS y asignarle un nombre de campo, en caso de no hacerlo podemos tener ciertos inconvenientes al trabajar con las tablas, siempre es importante asignarle un ALIAS en caso de crear campos adicionales, si nos fijamos con detenimiento, entendemos que en dicha consulta, nosotros estamos creando el campo NOMBRE, con la concatenación de tres campos. Esto último contesta, porque en el ORDER BY ponemos NOMBRE, esto es así, porque DISTINCT solo admite en el ORDER BY, nombres de campo en la consulta, como el campo que mostramos, es un campo que creamos nosotros, la única manera de realizar un orden de nuestro resultado es instanciando nuestro campo NOMBRE, también en el ORDER BY podemos poner la suma de los tres campos tal cual en la consulta SELECT (sin el AS), pero queda un poco más desprolijo, pruébenlo y verán que funciona!

Por último, supongamos que solo queremos ver los primeros 100 que aparecen en la tabla y los demás descartarlos... Bueno para eso podemos utilizar el predicado TOP, y es tan simple como lo siguiente:
SELECT DISTINCT TOP 100
  ISNULL(PE.LastName, '') + ', ' + ISNULL(PE.FirstName, '') + ' ' + ISNULL(PE.MiddleName, '') AS NOMBRE
   FROM [PERSON].[PERSON] AS PE
ORDER BY 
  NOMBRE ASC

Donde el número 100 es la cantidad de registros que queremos mostrar.
Bueno, esto es todo, pero no nos olvidemos que esto es solamente una pequeña parte de la consulta SELECT, es muchísimo más completa!, pero lo dejaremos para la próxima, en el siguiente artículo.

Si encuentran algún detalle en la entrada no duden en decírmelo, espero que les sea de gran utilidad. Hasta la próxima.
No duden en visitar todos los articulos de esta tematica en la recopilacion de articulos para SQL

No hay comentarios:

Publicar un comentario