Buscar este blog

jueves, 27 de septiembre de 2012

Puzzles en T-SQL ¿te atreves a encontrar la respuesta?

Recientemente, Pinal Dave publicó en su blog SQL Authority un post con dos puzzles para Transact SQL. La curiosidad nos hizo intentar averiguar las respuestas, y aquí va lo que descubrimos (podéis intentar adivinarlas antes de leer la solución):



Puzzle 1. ¿Por qué la siguiente query produce como resultado un asterisco (*)?
SELECT CAST (100 AS varchar(2))
Podríamos esperar un error de desbordamiento, que el 100 se truncara por alguna de sus extramos y quedase reducido a un 10 o a un doble cero (00). Pero no, SQL Server nos retorna un asterisco.

Solución: La MSDN nos explica cómo actúa el motor de la base de datos a la hora de convertir un número (smallint, int...) a una cadena. Si la cadena soporta caracteres Unicode (nchar o nvarchar), se producirá un error. Sin embargo, si estamos intentando convertir el número en un char o varchar con menor longitud de la necesaria, obtendremos un asterisco. Dicho asterisco -nos explica el artículo- quiere decir que la longitud resultante es demasiado corta para mostrar el valor.

Conversiones de números en cadenas de tamaño insuficiente, según la MSDN
Puzzle 2. ¿Cuál es la sentencia más corta que produce un 1 como resultado, sin usar números?

Para esta pregunta encontramos una discusión abierta en el grupo SQL Server Developers de LinkedIn. Allí, el ingenio de algunos de los participantes nos llevó a respuestas cada vez más cortas. Os intentamos explicar cada una de ellas.

Solución: Inicialmente nos encontramos con la siguiente query:
SELECT COUNT(*)
COUNT(*) nos devuelve el recuento del número de filas afectadas por la sentencia SELECT. Como no estamos devolviendo filas de una tabla, SQL asume que el número de filas devueltas es uno (como si ejecutásemos una SELECT de una lista de valores constantes - SELECT constante1, N'constante2', dia-mes-año...)

Con la misma longitud existe otra solución: Pedirle a SQL Server la longitud de una cadena de texto de un solo carácter. Así:
SELECT LEN('a')
Buenos intentos, pero se pueden mejorar. SQL Server acepta los tipos de datos money y smallmoney. Para representar estos tipos de datos, se pueden usar símbolos de moneda. Así, 100€ se pueden representar como €100. Si dejamos la parte numérica vacía, SQL Server interpreta que la cantidad es cero. Así, SELECT $ nos devolvería 0.00.

A partir de un cero, ¿qué funciones SQL nos pueden devolver un uno? Son las siguientes:


SELECT EXP($) -- El número e elevado a cero es uno.
SELECT DAY($) -- El día cero para SQL Server es el 1 de enero de 1900, así que cogemos el día
SELECT COS($) -- El coseno de 0 es 1.


¿Podéis mejorarlo? :)

1 comentario: