Operadores de conjunto en SQL-Server: UNION, INTERSECT y EXCEPT

Los operadores de conjunto UNION, INTERSECT y EXCEPT nos permite combinar en una misma salida el resultado de distintas consultas SELECT, construyendo así una consulta más compleja, lo que se llama una consulta compuesta. Para poder combinar dos consultas con estos operadores necesitamos que se cumplan dos requisitos:

  • Que ambas consultas devuelvan el mismo número de columnas.
  • Que estas columnas contengan el mismo tipo de datos, o al menos tipos de datos que se puedan convertir de forma implícita.

Estos tres operadores se incorporaron a SQL-Server a partir de la versión 2008 y están también disponibles en la base de datos SQL de la plataforma Azure. Los tres operadores aceptan además el parámetro ALL, que modificará ligeramente los resultados ¿Cómo funcionan y qué diferencia hay entre ellas?

EXCEPT:

Este operador encuentra la diferencia entre las dos consultas y devuelve las filas que pertenecen únicamente a la primera consulta. Es decir, si una tupla aparece tanto en la consulta de la izquierda como en la de la derecha no será incluida en el resultado final. Si aparece solo en la de izquierda y en la de la derecha no, entonces será devuelta una vez.

Si añadimos ALL al EXCEPT notaremos una pequeña diferencia. Al igual que con el EXCEPT a secas el operador buscará la diferencia entre las dos consultas, pero los datos devueltos cambian. En este caso si una tupla aparece un número m de veces en la primera consulta, y la misma tupla aparece un número n veces en la segunda consulta, entonces esa tupla aparece m – n veces en la respuesta de salida, si dicha resta es mayor que 0.

/*consultamos una tabla de Productos 
y sacamos todos los resultados únicos 
que no que existen en la consulta sobre la tabla Almacén*/

Select Descripcion, Codigo from Productos
EXCEPT
Select Descripcion, Codigo from Almacen

/*Con ALL si la tupa Descripción,Codigo existiese tres veces
en el resultado de la primera consulta y una vez en la segunda
entonces en el resultado final saldría dos veces*/
Select Descripcion, Codigo from Productos
EXCEPT ALL
Select Descripcion, Codigo from Almacen

INTERSECT:

Este operador combina los resultados de dos consultas en un único resultado que comprime todas las filas comunes para ambas consultas. Es decir, funcionaría como un AND lógico: devuelve solo las ocurrencias existentes en ambas consultas.

Si añadimos ALL a este operador el resultado también cambiará. En ese caso si una tupla aparece un número m de veces en el resultado de la primera consulta y la misma tupla aparece n veces en la segunda, entonces esa tupla aparece el menor número de entre m o n en la respuesta de salida.

/*consultamos una tabla de Productos 
y sacamos todos los resultados únicos 
que también existen en la consulta sobre la tabla Almacén*/

Select Descripcion, Codigo from Productos
INTERSECT
Select Descripcion, Codigo from Almacen

/*Con ALL si la tupa Descripción,Codigo existiese tres veces
en el resultado de la primera consulta y una vez en la segunda
entonces en el resultado final saldría una vez solo*/
Select Descripcion, Codigo from Productos
INTERSECT ALL
Select Descripcion, Codigo from Almacen

UNION:

Finalmente vamos con UNION. Si antes os decía que INTERSECT funciona como un operador lógico AND entonces UNION funcionaría como un operador lógico OR. Devuelve las filas únicas que existen o en la consulta de la izquierda o en la de la derecha.

En este caso el operador ALL lo que hará será modificar el resultado del UNION de forma que en lugar de recibir solo las filas únicas recibamos tantas filas como haya en la primera consulta y en la segunda, un poco la operación contraria a la que realiza EXCEPT ALL. En este caso si una tupla aparece un número m de veces en la primera consulta, y la misma tupla aparece un número n veces en la segunda consulta, entonces esa tupla aparece m + n veces en la respuesta de salida.

/*consultamos una tabla de Productos 
y la tabla Almacén y sacamos los resultados únicos, distintos*/

Select Descripcion, Codigo from Productos
UNION
Select Descripcion, Codigo from Almacen

/*Con ALL si la tupa Descripción,Codigo existiese tres veces
en el resultado de la primera consulta y una vez en la segunda
entonces en el resultado final saldría cuatro veces*/
Select Descripcion, Codigo from Productos
UNION ALL
Select Descripcion, Codigo from Almacen

Añadir un PDF a un sitio web usando una etiqueta de HTML5

Existen varias formas de insertar un PDF dentro de un sitio web, una de ellas es usar alguna de estas etiquetas:

  • embed
  • object
  • iframe

Antaño solo teníamos la opción de usar la etiqueta iframe, dado que embed y object se añadieron para la especificación HTML5. En todo caso el procedimiento con las tres es el mismo: ponemos la URL del fichero PDF como valor del atributo src y definimos el tamaño mediante los atributos width y height:

<!--Ejemplos varios-->
<iframe src="http://rutaamipdf/fichero.pdf" width="95%" height="100%"></iframe>

<embed src="http://rutaamipdf/fichero.pdf" width="95%" height="100%"></embed>

<object src="http://rutaamipdf/fichero.pdf" width="95%" height="100%"></object>

¿Problemas? Pues sí, que con este método dependemos de que el navegador que está usando el usuario tenga incorporado algún visualizador de PDF. En algunos casos tiene que ser mediante un plugin externo, como en Chrome, en otros ya viene incluído por defecto en el propio navegador.

Comprobar de forma fácil si un número es par en una hoja de cálculo de Google Drive

En su día habíamos visto varias soluciones para comprobar con PHP si un número es par o impar. Esto también podemos necesitarlo cuando trabajamos con una hoja de cálculo de Google Drive, por suerte ya hay una función específica para ello:

La funció ES.PAR() recibe un número como parámetro y nos devuelve un valor booleno: verdadero si es par y falso si no lo es. Así de simple. Su funcionamiento sería como en el siguiente ejemplo:

=ES.PAR(22)

Importar datos de una hoja de cálculo de Google Drive a otra con IMPORTRANGE()

En los últimos tiempos casi todos los artículos técnicos están siendo de ofimática y, más en concreto, de Google Drive. Y esta nueva entrega sigue por ahí: ¿podemos importar datos de una hoja de cálculo a otra en Google Drive? Pues sí, podemos.

La función IMPORTRANGE() se encarga de ello, recibiendo dos parámetros (dos cadenas de texto, por tanto se les envían siempre entre comillas dobles): el primer parámetro será la URL de la hoja de cálculo donde está el origen de los datos, el segundo será una cadena donde especificamos la hoja y el rango de celdas a recoger. La sintaxis es tal que así:

=IMPORTRANGE("UrlDeLaHojaDeCálculo";"NombreDeLaHoja!CeldaInicio:CeldaFin")

Os voy a dejar un ejemplo más o menos real. Tengo una hoja de cálculo donde voy guardando los discos que añadiré a la próxima revisión de los 1100 discos esenciales (cuando crezca hasta 1250, dentro de unos meses). Ahora voy a importar de esa tabla las dos primeras columnas de las 20 primeras filas. Lo haría así:

=IMPORTRANGE("https://docs.google.com/spreadsheets/d/1QqGx-f4jC3ZHi1jkSa9eY9_vY-OiClXJ1nKTDwleVpfh3I/";"Hoja 1!A1:B20")

Otro dato importante: por seguridad la primera vez que importemos los datos se nos solicitará conceder permisos explícitamente sobre la hoja de origen. Una vez concedidos, la hoja de cálculo de destino podrá extraer datos de cualquier parte de la hoja de origen hasta que el permiso se revoque también de forma explícita.

Importar datos desde una web a una hoja de cálculo de Google Drive

Seguimos con el tema de la ofimática y con las hojas de cálculo de Google Drive, que parece ser un material que os interesa. Hoy vamos a ver una función muy útil aunque un poco liosa: Con IMPORTHTML() podemos importar a la hoja tablas o listados de una web.

La función recibe tres parámetros: el primero, como es lógico, es la URL de la página desde la que queremos importar los datos, irá entre comillas dobles por ser una cadena de texto. El segundo, el formato que queremos importar (puede ser «table» para tablas o «list» para listas». Finalmente el tercero es un índice para indicar qué tabla quieres traer si hay varias dentro de la web, algo que puede ser lioso ya que a veces vamos «a ciegas» y puede que necesitemos varios ensayos de prueba y error hasta traer el dato que queremos. Por tanto la sintaxis sería tal que así:

=IMPORTHTML (dirección url; tipo de listado; índice numérico)

Vamos con un caso práctico, seguro que recuerdas que en su día vimos como exportar datos desde la web Basketball-Reference a formato Excel. Ahora vamos a hacer lo mismo pero usando directamente esta fórmula en una hoja de Google Drive:

=IMPORTHTML("https://www.basketball-reference.com/players/s/smithjr01.html";"table";1)

La línea de arriba importaría la primera tabla de la ficha de JR Smith, es decir, sus promedios en temporada regular. El resultado sería tal que así:

Ejecutar apps de Android en Linux con Anbox

Aunque el núcleo de Android es Linux sus aplicaciones no son compatibles de forma nativa con una distribución de GNU/Linux. Para correr aplicaciones Android en un sistema Linux necesitamos un emulador al estilo de Wine (que nos permite correr aplicaciones de Windows).

Existen hoy por hoy varios proyectos de emuladores que nos permiten hacer esto en nuestros sistemas Linux pero ha sido Anbox el que me ha parecido más interesante ¿por qué? Porque Anbox se sirve del propio kernel de nuestra distribución para trabajar, sobre el que extiende una capa de compatibilidad. ¿Qué implica esto? Que al no tener que emular el kernel consume menos recursos que sus competidores. Nuestro hardware queda menos cargado con el.

Podemos instalarlo mediante paquetes snap o desde la tienda de apps o los repositorios de nuestra distro. Una vez instalado basta con instalar en nuestro equipo el .apk de la aplicación que queremos correr. Para facilitar esta instalación lo mejor es que instalemos también AndroidDebugBridge (ADB), una herramienta para desarrolladores Android:

# Instalar ADB en Ubuntu y familia
$ sudo apt install android-tools-adb

# Instalar ADB en Fedora
$ sudo dnf install android-tools

La función SPARKLINE() en la hoja de cálculo de Google Drive: insertar gráficas en una celda

Si bien la hoja de cálculo de Google Drive, al igual que Excel o que LibreOffice Calc, nos aporta una serie de cómodas herramientas para la creación de gráficos también disponemos de una función que nos permite crear un gráfico dentro de una celda. Dicha fución se llama SPARKLINE().

Ejemplo con los cuatro tipos de gráficos disponibles.

Esta función recibe como primer parámetro el rango de celdas del que queremos recoger los valores. Opcionalmente puede recibir un array de valores como parámetros opcionales. Estas opciones serían pares de valores, irían encerradas entre llaves, separadas del rango por un punto y coma. La separación entre pares se marcaría con un punto y coma, y dentro de cada par con el carácter de la barra \. Debajo te dejo un ejemplo porque explicado así es un lío:

=SPARKLINE(C1:C25,{"charttype"\"bar";"max"\50;"empty"\"zero"})

El parámetro «charttype» indicaría el tipo de gráfico y puede tener los siguientes valores:

  • line: es el valor por defecto, el que tomasi no se especifica ninguno, genera un gráfico de líneas.
  • bar: genera un gráfico de barras apiladas.
  • column: genera un gráfico de columnas
  • winloss: es un gráfico de barras pero que solo representa si el valor es positivo o negativo.

En la imagen de arriba podéis ver cómo se visualizarían los cuatro. Para cada tipo de gráficos tienes después una serie de opciones, que puedes consultar en la documentación oficial de Google.

La función DETECTLANGUAGE() en la hoja de cálculo de Google Drive

Si no hace mucho veíamos cómo usar la función GOOGLETRANSLATE() para traducir el texto en una celda de una hoja de cálculo de Google Drive tenemos una opción similar: detectar el idioma de una celda.

Para eso nos serviremos de la función DETECTLANGUAGE(), que recibe como parámetro una cadena de texto y devuelve el código del idioma que corresponda. Tal que así:

=DETECTLANGUAGE(«Olá, bom dia») por ejemplo nos devolvería el código «PT» de portugués.

La función lógica CHOOSE() en SQL-Server

La función lógica CHOOSE() se añadió a SQL-Server desde la versión 2012, y su funcionamiento es similar a recuperar valores de un array. Es una función que recibe al menos tres valores: el primero, que será un valor índice, y tras él una serie de valores separados por comas, requeríendose al menos dos. La función devolverá el valor de la lista que coincida posicionalmente con el valor del índice.

Veámoslo con un ejemplo simple:

--Esto devolvería "Pringao" por ser el tercer valor:
SELECT CHOOSE ( 3, 'Jefazo', 'Jefecillo', 'Pringao', 'Becario' ) AS TuPuesto  

Lógicamente el primer valor no tiene por qué ser una constante, puede salir de una consulta. Veámoslo en un ejemplo similar al de arriba:

--Si el IdPuesto es 1 devuelve "Jefazo", si es 4 devuelve "Becario"
SELECT IdPuesto, CHOOSE ( IdPuesto, 'Jefazo', 'Jefecillo', 'Pringao', 'Becario' ) AS NombrePuesto from Plantilla  

O de una variable:

SELECT @Puesto, CHOOSE ( @Puesto, 'Jefazo', 'Jefecillo', 'Pringao', 'Becario' ) AS NombrePuesto from Plantilla 


Conocer tu ip externa desde línea de comandos en Linux con wget

Hace tiempo habíamos visto por aquí cómo conocer nuestra IP externa desde línea de comandos en Linux con cURL. Pero hay más métodos. Veamos hoy cómo hacerlo con wget, de nuevo recurriendo a la web ifconfig.me para ello (como en ejemplo de cURL):

wget -qO - ifconfig.me/ip

El API de ifconfig.me además nos permite conocer otras cosas como nuestro user agent, el puerto por el que conectamos, el idioma predefinido con el que navegamos… en la página principal podéis ver, debajo de vuestros datos, todos los comandos disponibles.