Concatenar varios valores de la misma columna en una sola celda en SQL-Server

Esta tarde, para hacer un informe en una aplicación en el trabajo (SQL-Server+ASP+VB), necesitaba sacar todos los registros de una columna en un solo registro separado por un símbolo. Podéis decir que podría haber hecho una consulta normal y luego simplemente añadir las comas al imprimirla en pantalla, pero en este caso necesitaba que vinieran así en la consulta SQL.

Si bien en un principio pensé en utilizar un cursor, al final rebuscando por el manual de SQL-Server 2008 (que debe ser de los pocos que tengo en papel y no en PDF) encontré una solución que consume menos recursos.

Empecemos con la tabla, más o menos esta

CREATE TABLE Problemas(
Id INT PRIMARY KEY IDENTITY(1,1),
Incidencia VARCHAR(120),
Usuario INT,
Fecha DATETIME
)

Bien, la cosa es tener una cadena con todas las incidencias separadas por una «tubería» (el caracter | ).

El procedimiento va a ser el siguiente: declaramos una variable, hacemos un select donde vayamos concatenando cada resultado dentro de la variable, hacemos un apañico porque nos va a meter un separador al principio y acabamos con un select sobre la variable para mostrarla/recogerla.

--Declaramos la variable
DECLARE @ListaIncidencias VARCHAR(MAX) = ''
--Ahora vamos con la consulta
SELECT @ListaIncidencias = @ListaIncidencias +'|' + p.Incidencia
FROM Problemas p
--Eliminamos el separador extra que nos meterá al principio
--usando SUBSTRING
SET @ListaIncidencias = SUBSTRING(@ListaIncidencias,2,LEN(@ListaIncidencias))
--Hacemos un SELECT sobre la variable para sacarla por pantalla
SELECT @ListaIncidencias as 'Incidencias'

De esta forma todos los registros aparecerán como una cadena de texto dentro de una sola celda.

Diferencia entre inner join, left join y right join. SQL

Hoy otra cuestión a petición de un lector que decía que su nivel de inglés no era el suficiente para orientarse con la muy válida explicación que hay en StackOverflow que hasta incluye este útil diagrama:

Uniones entre tablas SQL
Diferentes tipos de uniones entre tablas

Si bien finalmente encontró una válida explicación en otras páginas (hay unas cuantas) me da pie para esta entrada. ¿Qué diferencia hay entre un inner join y un left o un right join?

Las más comunes suelen ser las uniones internas entre tablas (inner join), como ejemplo os diré que en los últimos seis meses, desde que empecé en mi actual trabajo, he tenido que hacer sólo 3 uniones externas mientras que internas he hecho docenas. Un inner join, si miráis el diagrama, se podría representar como la intersección entre dos conjuntos, es decir, una consulta con inner join mostraría los registros de las tablas que coincidan en los campos de la unión que se ha definido en dicha consulta. Dicho así es denso, pero con un ejemplo se entiende claro.

Supongamos que tenemos una tabla con los empleados de una empresa (con un identificador llamado Id, un campo de nombre, uno de apellidos y uno con el Id del departamento en que trabaja llamado IdDepartamento) y en otra tenemos los departamentos (Id y Nombre). Algunos trabajadores tienen un departamento asignado y otros no, y obviamente la relación entre ambas tablas se da entre el campo Id de Departamento con el campo IdDepartamento de la tabla Empleados. Utilizando un inner join podríamos obtener el listado de todos los trabajadores que tienen un departamento asignado:

select e.nombre, e.apellidos from empleados e inner join departamentos d on e.IdDepartamento=d.Id;

En cuanto al enlace externo tenemos dos opciones: left join y right join. Con esta unión recuperamos todos los enlaces de una tabla y los datos de la otra que coinciden con la condición definida en la consulta. Cuando usamos una unión left join recogemos todos los datos de la tabla que está a la izquierda de la unión en la consulta y si usamos en cambio right join las de la derecha. Imaginemos las tablas de antes, pero ahora queremos todos los datos de la tabla empleados, tengan o no departamento, y además el dato de en qué departamento están si lo tuvieran. Usaremos un left join para obtener los datos.

select e.nombre, e.apellidos from empleados e left join departamentos d on e.IdDepartamento=d.Id

En este caso obtendríamos los nombres y apellidos de todos los empleados, los departamentos de los que lo tenga y en los que no recibiríamos un campo con un valor NULL.

Finalmetne tendríamos opciones como el full outer join o producto cartesiano, que nos sacaría todos los valores de ambas tablas.

A partir de esto y mezclando varias tablas y condiciones extra en una cláusula WHERE podemos lograr resultados más complejos.

Etiquetas para convertir webs en web-apps Android

No hace mucho os hablaba aquí de una serie de etiquetas creadas por Apple que permitían hacer que una web luciera como una aplicación nativa de iOS, y comentaba que era una pena que no hubiera algo así para Android… pero lo cierto es que lo hay. A partir de la salida de Chrome 31 para Android el sistema operativo de Google también da opción a hacer esto mismo, aunque he de admitir que no dan tanto juego como las de Apple, y como estos se han dedicado (como es su filosofía de empresa hermética/cabrona/malvada) a no documentar ni compartir una mierda hay que andar buscándose la vida. Por cierto que Mozilla también nos permite crear web-apps facilitas tanto para su sistema operativo FirefoxOS como para Amazon Kindle Fire y Android si usas Firefox.

De primeras no hay una etiqueta especial para el título del app, deberéis utilizar la meta etiqueta title normal. Tampoco existe un equivalente de la propiedad navigator.standalone de iOS, que nos devuelve un boolean si estamos ejecutando el app a pantalla completa. En todo caso, con este truquito podemos lograr lo mismo:

navigator.standalone = navigator.standalone || (screen.height-document.documentElement.clientHeight<40)

El Javascript ejecutadlo siempre después de que la página esté totalmente cargada (tras el evento onload()), por si los scrolls.

Vamos ahora con los puntos fundamentales. El primero: forzar el modo web-app, que se consigue con la siguiente etiqueta:

<meta name="mobile-web-app-capable" content="yes">

Vamos, lo mismo que la de iOS quitándole el prefijo «apple». El segundo punto clave ¿cómo añadir al escritorio el app? Bueno, la primera vez que llegáis a la página, en el menú del navegador os encontráis una opción que será “Add to homescreen” (lo he probado en emulador y tengo Chrome en inglés, no estoy seguro de cómo se llama la opción en castellano). En cuanto al icono, si habéis puesto el de Apple Touch lo cogerá por defecto, si bien la especificación de google recomienda incluir uno cuadrado de 196*196, tal que aśi:

<link rel="shortcut icon" sizes="196x196" href="vuestroIcono.png">

Un último punto, los enlaces se abrirán por defecto en el contexto de la aplicación, si queréis abrir un enlace concreto en una ventana de Chrome (por ejemplo una referencia a una web externa) insertad el atributo target=»_blank» en el link.Otro punto, no tenéis el botón de recargar del navegador (al estar en ese contexto sin marco), así que si queréis tener una opción de «refresh» tendréis que implementar una solución en javascript.

En fin, queda mucho por andar en este terreno, pero parece que Google se pone al fin las pilas, y Mozilla ya lleva mucho currando (y al contrario que Apple ellos sí hacen las cosas de forma abierta).

PHP: Diferencia entre == y ===

A la hora de realizar comparaciones en PHP disponemos de dos operadores == y ===, hoy me han preguntado en qué se diferencian, así que he pensado que no es mala idea explicarlo también aquí.

PHP es un lenguaje muy flexible en cuanto a los tipos de datos, puedes tener una variable con una cadena y compararla con un entero… y no sufrirás la hecatombe que te encontrarías con C o ASP. Y esto es lo que explica la existencia de dos operadores de comparación: == comprueba que los valores sean iguales, independientemente del tipo ya que realiza una conversión antes de comparar. En cambio el operador === comprueba que además de coincidir los valores también coincidan los tipos. Con un pequeño ejemplo se entiende perfectamente

/*Damos a una variable un valor entero*/
$var1 = 0;
/*Damos a otra un valor booleano*/
$var2 = FALSE
/*Si los comparamos con == verás como cumple el condicional, ya que tratará a ambos como booleanos*/
if($var1 == $var2){
  echo "Son iguales"
}
/*En cambio con === no entraría porque no realiza la conversión, de esta forma al tratarse de tipos distintos no entra*/
if($var1 === $var2){
  echo "Son idénticos"
}

CouchCMS: Creando una región editable con sólo una etiqueta

No hace mucho me hablaron de CouchCMS en Facebook, un CMS open source (que no libre) ligero y flexible. Apenas he podido trabajar con él todavía porque cada día ando más liado con proyectos varios (y en el curro, de momento, el que quiera CMS va a chupar WordPress por un tubo, que para algo es por el que mejor me muevo de momento).

En todo caso una de las ventajas de este cms es que nos permite fácilmente definir una región de nuestro HTML como editable, de forma que el usuario pueda cambiar fácilmente su contenido desde el panel de administración, como si de una publicación en un blog se tratara.

Vamos a suponer que ya tienes instalado el CMS en tu servidor y que dispones de una web estática HTML, en la que quieres declarar como editable una región. Lo primero es cambiar la extensión de tu archivo .html por .php y, lo siguiente, es añadir antes de la cabecera del HTML el script cms.php desde la carpeta donde guardaras el Couch:

<?php require_once( 'couch/cms.php' ); ?>

Y al final del archivo, en la última línea, la llamada a ejecución de Couch:

<?php COUCH::invoke(); ?>

Con esto tenemos CouchCMS funcionando sobre nuestra vieja página HTML estática. Ahora vamos a con el siguiente paso: declarar editable una región. Para esto basta con usar un par de etiquetas.

<!-- Imaginemos que este es nuestro código inicial -->
<h3>Le título!</h3>
<p>Un parrafillo estático del todo</p>

<!-- Con estas etiquetas ya sería editable la región -->
<h3>Le título!</h3>
<cms:editable name='contenido' type='richtext'>
<p>Un parrafillo estático del todo</p>
</cms:editable>

La etiqueta cms:editable es la que define como tal una región (ok, esto es de captain obvious). El nombre que le demos debería ser único, ya que cuando entremos a la zona de administración del cms la región será identificada con dicho nombre en el editor. En el type hemos puesto, ya que será un texto, richtext para poder modificarla y formatear con un editor WYSIWYG, si bien existen muchas posibilidades.

Próximamente, cuando vaya explorando un poco, iré añadiendo más cosas sobre este cms.

Clases para imágenes en Twitter Bootstrap

Hacía tiempo que no tocaba un post «por encargo», pero me han comentado por Twitter que hable de las clases que el framework Bootstrap nos ofrece para trabajar con imágenes. No son muchas, la verdad, y de hecho están recogidas en su documentación oficial. Pero en fin, allá vamos.

Básicamente, en cuanto a la forma de la imagen, Bootstrap nos ofrece tres clases para tres resultados distintos: rounded, circle y thumbnail. La primera hará que la imagen tenga bordes redondeados, la segunda que esta sea circular y la tercera le pondrá un marco alrededor. El ejemplillo en código sería:`

<!--Bordes redondeados-->
<img src="carpeta/archivo.extension" alt="Texto1" class="img-rounded">
<!--Circular-->
<img src="carpeta/otroarchivo.extension" alt="Texto3" class="img-circle">
<!--Thumbnail con marco-->
<img src="otracarpeta/archivo.extension" alt="Texto5" class="img-thumbnail">

También hay una clase para imágenes responsivas, que básicamente aplica un max-width del 100% y un height automático, lo que hace que su tamaño se adapte al de su elemento padre. En ese caso se usar la clase img-responsive:

<img src="carpeta/imagen.extension" class="img-responsive" alt="Imagen de tamaño adaptable">

Y ya está todo el pescao vendido, no hay más que rascar en este tema (aunque sí en Bootstrap, un estupendo framework para el desarrollo de front end)

Crear un hexágono o un octógono con CSS

Se está poniendo de moda el usar formas geométricas en las maquetaciones así que ¿cómo podemos crear un hexágono para nuestra web? ¿o un octógono? En el último año de hecho los hexágonos han estado bastante de moda (parece un chiste, pero no, pensad en múltiples diseños que habéis visto)

Entonces ¿cómo creo un hexágono con CSS? Pues aquí va un ejemplo de código, basándose en un la idea de que, a fin de cuentas, un hexágono se hace con un cuadrado con un triángulo encima y otro debajo:

#hexagono { 
  width: 150px; 
  height: 90px; 
  background: #666; 
  position: relative; 
}

#hexagono:before { 
  content: ""; 
  position: absolute; 
  top: -50px; 
  left: 0; 
  width: 0; 
  height: 0; 
  border-left: 75px solid transparent; 
  border-right: 75px solid transparent; 
  border-bottom: 50px solid #666; 
} 
#hexagono:after { 
  content: ""; 
  position: absolute; 
  bottom: -50px; 
  left: 0; 
  width: 0; 
  height: 0; 
  border-left: 75px solid transparent; 
  border-right: 75px solid transparent; 
  border-top: 50px solid #666;  
}

Ya véis la idea: usando :after y :before metemos dos triángulitos sobre un cuadrado y ya tenemos hexágono.

El octógono ya es más jodón, que tiene más lados, pero tampoco entraña mucha más complejidad. Eso sí, vas a necesitar jugar con más colores, ya que las formas se hacen a base de bordes, como en el ejemplo anterior:

#octogono { 
  width: 150px; 
  height: 150px; 
  background: #999; 
  position: relative; 
} 
#octogono:before { 
  content: ""; 
  position: absolute; 
  top: 0; 
  left: 0; 
  border-bottom: 44px solid #999; 
  border-left: 44px solid #fff;/*Para el ejemplo he elegido blanco, poned vosotros el color de fondo de vuestra web. No uséis transparent porque entonces se verá el color de fondo del cuadrado*/ 
  border-right: 44px solid #fff; 
  width: 63px; height: 0; 
} 

#octogono:after { 
  content: ""; 
  position: absolute; 
  bottom: 0; 
  left: 0; 
  border-top: 44px solid #999; 
  border-left: 44px solid #fff; 
  border-right: 44px solid #fff; 
  width: 63px; 
  height: 0; }

Acceder a los elementos de un Iframe con Javascript

Un tip rápido de Javascript: Tienes un iframe en tu página y quieres acceder a los elementos que hay dentro. ¿Es posible hacerlo? Sí pero no. Me explico:

Si el iframe está en el mismo dominio que la página padre sí, si no, por motivos de seguridad, el navegador no te lo permitirá.

En caso de que la respuesta a si está en el mismo dominio sea afirmativa puedes acceder al iframe por su id, ya que habrá un objeto donde estarán guardados todos, y una vez accedido a él puedes llegar a sus elementos a través de su id. Un ejemplo simple:

// cambia miFrame por el id de tu iframe,
// cambia idDelElemento por el id que corresponda,
// puedes trabajar con los elementos del iframe como si fueran parte de la página padre.
window.frames['miFrame'].document.getElementById('idDelElemento')

Añadiendo elementos al DOM con Javascript: appendChild e insertBefore

Una de las funcionalidades potentes de Javascript es poder generar nuevo código dinámicamente y añadirlo a nuestra web, cosa que podemos hacer con las funciones appendChild e insertBefore.

El método appendChild nos permite insertar un elemento dentro de otro, al final del mismo. Imagina que quieres agregar un elemento a una lista que sea «nuevo elemento«, pues javascript permite crear este nuevo elemento, meterle un nodo de texto y agregarlo a la lista. Veamos como:

elemento1 = document.createElement('li');
elemento1.appendChild(document.createTextNode('nuevo elemento'));
elemento2 = document.getElementById('laListaQueYaExiste');
elemento2.appendChild(elemento1);

¿Y si quieres insertar al principio en lugar de al final de la lista? Pues tan simple como usar insertBefore:

elemento1 = document.createElement('li');
elemento1.appendChild(document.createTextNode('nuevo elemento'));
elementoLista = document.getElementById('laListaQueYaExiste');
//hasta aquí todo igual
elemento2 = elementoLista.firstChild();
//en la línea de arriba creamos un elemento nuevo que es el primer elemento de la lista.
elemento3.parentNode.insertBefore(elemento1,elemento3);
//también podríamos haberlo hecho así:
elementoLista.insertBefore(elemento1,elemento3);