Funciones lógicas en las hojas de cálculo de Google Drive

Hace unos años habláramos aquí de funciones lógicas en LibreOffice. En aquel entonces ya existía Google Drive pero no conocía a mucha gente que lo utilizara para sus labores ofimáticas. Hoy por hoy su uso se ha popularizado bastante, así que mi idea es repetir la misma entrada, pero con las funciones lógicas de esta hoja de cálculo que, más o menos, son similares (aunque en caso del Drive son menos que en LibreOffice, se quedan en 7). Lo primero que veremos, la lista de funciones:

  • FALSO: Una función que no evalúa ningún dato, sólo devuelve el valor lógico false.
  • VERDADERO: Una función que no evalúa ningún dato, sólo devuelve el valor lógico true.
  • NO: Recibe una expresión lógica, su sintaxis sería NO(La_Expresión_Lógica) y devuelve el valor contrario al que recibe. Es decir, si la expresión que recibe es true la función devolverá false y viceversa.
  • SI: Esta función requiere tres parámetros que son una prueba lógica, un valor a devolver si se cumple y un valor a devolver si no, aunque sólo es obligatoria la prueba lógica. Más abajo os explicaré como anidar varios. La sintaxis básica es SI(prueba lógica; valor si se cumple; valor si no).
  • SI.ERROR: Función que recibe dos parámetros. Devuelve el valor del primero si este no es erróneo, en caso de que lo sea devuelve el segundo. La sintaxis es SI.ERROR(valor_a_evaluar,valor_si_error)
  • O: La función recibe varios argumentos y devuelve true en caso de que alguno sea verdadero, en caso de todos sean falsos devuelve false. La sintaxis es O(expresión1,expresión2,expresión3)
  • Y: La función recibe un número variable de argumentos. En caso de que todos sean verdaderos devuelve true y caso de que alguno sea false devuelve false. La sintaxis es Y(expresión1,expresión2,expresión3)

Ahora vamos con un ejemplo. Primero tenemos estos datos con nombres de usuarios, su ciudad y su edad. En base a la edad y la ciudad calcularemos un importe que tienen que pagar usando algunas de estas funciones lógicas. Las condiciones son las siguientes: si son de Madrid y mayores de 28 entonces pagan 100. Si son de Vigo, de Basauri o tienen más de 50 años entonces pagan 50. El resto pagan 200.

Ejemplo Drive Hoja Calculo 1

La función sería la siguiente:

=SI(Y(C2=«Madrid»;B2>28);100;SI(O(C2=«Vigo»;C2=«Basauri»;B2>50);50;200))

Aunque una vez la escribáis os la traducirá a la nomenclartura inglesa de las funciones:

=IF(AND(C3=«Madrid»;B3>28);100;IF(OR(C3=«Vigo»;C3=«Basauri»;B3>50);50;200))

Y el resultado de esos datos sería el siguiente:

Ejemplo con los datos calculados

Mostrar asteriscos en la consola de Mac o de Linux al escribir una contraseña

Una de las cosas que más despistan cuando se empieza a trabajar con la línea de comandos de sistemas operativos basados en UNIX es que al poner una contraseña no se muestra nada. La parte buena es que si tenemos a alguien mirando por encima de nuestros hombros no le damos una pista de la longitud de nuestra contraseña, la mala es que no sabemos si hemos tecleado mal. Pero ¿se puede hacer que muestre unos asteriscos cuando la introducimos? Se puede:

Lo primero, editar el fichero de sudoers:

sudo visudo

Lo siguiente, buscar la línea que pone esto:

Defaults        env_reset

Lo tercero, modificar la línea para que luzca así:

Defaults        env_reset,pwfeedback

Esto funciona en la mayoría de linux modernos y en los Mac con OS X superior al 10.8, así que si quieres esta ayuda visual seguramente podrás disfrutarla.

Linux: crear una contraseña aleatoria simple

Hemos visto un par de formas de generar claves aleatorias en Linux. Vamos a ver otra que no es especialmente compleja. No es lo más seguro para generar una serie de claves aleatorias ni da un resultado especialmente recordable, pero para un apuro te permite salir del paso en la consola cualquier distribución y sin instalar software:

date|md5sum

Tan simple como esto: tomamos la fecha en tiempo UNIX y le aplicamos la función de resumen md5.

Utilizar sudo sin contraseña

Arracamos 2018 con más Linux ¿Se puede configurar el sistema para no tener que poner la contraseña cuando invoquemos un comando precedido de sudo? Sí, se puede. ¿Se debe? No, eso debilita la seguridad y no es nada recomendable. ¿Entonces no se puede? Sí, se puede pero no se debe.

La cosa es editar el fichero /etc/sudoers utilizando el siguiente comando:

sudo visudo

Una vez lo estemos editando buscamos la línea que pone root ALL=(ALL) ALL y debajo añadimos la siguiente, cambiando nuestro_usuario por el nombre de usuario que corresponda.

nuestro_usuario ALL=(ALL) NOPASSWD: ALL

También podemos aplicarlo a grupos, para ello debemos poner el símbolo % seguido del nombre del grupo:

%nuestro_grupo ALL=(ALL) NOPASSWD: ALL

Y otra opción es permitirlo sólo a un comando, o serie de comandos. En ese caso cambiamos el ALL que va después de NOPASSWD por el comando en cuestión. En el ejemplo veremos como hacerlo para /bin/kill:

nuestro_usuario ALL=(ALL) NOPASSWD: /bin/kill

Y una vez guardados los cambios el sistema nos permitirá usar sudo sin contraseña. Y vuelvo a repetir: NO SE DEBE HACER. Pero si queréis hacerlo, ahí tenéis el cómo.

Generar contraseñas seguras en Linux con APG

Ya vimos en el pasado cómo generar contraseñas en linux con mkpasswd, hoy veremos otro método. APG, abreviatura de Automatic Password Generator, viene instalado en Ubuntu y sus derivados. Es un programa pensado para generar contraseñas «memorizables«. Si lo ejecutas a secas te pedirá una «raíz«, una serie de datos con los que trabajar, y en base a eso creará una contraseña «memorizable«, y con «memorizable» quiero decir que junto a la contraseña te mostrará una transcripción fonética para que la recuerdes mejor.

APG Ejemplo
Ejemplo de APG

También puedes generar contraseñas totalmente aleatorias usando el comando apg a -1, que ofrece resultados de entre 8 y 10 caracteres.

Ejemplo APG 2
Ejemplo de APG con a -1

Siete puntos a tener en cuenta para comprar on-line.

En estas fechas navideñas se hacen muchas compras, y en los últimos años las compras on-line han crecido exponencialmente. Tanto como para colapsar los centros de algunas empresas de transporte. Pero ¿Son seguras? En los últimos años la seguridad de estas transacciones también ha mejorado mucho, pero sin una serie de buenas prácticas por parte del usuario todo el trabajo de los programadores de dichos sistemas puede irse al garete.

Hace unas semanas, motivados por el Black Friday, INCIBE y OSI realizaron una guía con una serie de pasos para comprar de forma segura en Internet. Con ánimo divulgativo os dejo por aquí la infografía que realizaron y también este enlace donde podéis ver el contenido del post original en el sitio web de la OSI.

Guía OSI INCIBE compra on-line

 

SQL-Server. Vistas con índices ¿Cuándo no son recomendables?

Añadir un índice a las vistas en SQL-Server puede ser una buena idea para mejorar la velocidad de lectura en consultas sobre la misma, pero en determinados casos puede no ser recomendable ya que el mantenimiento de estos índices penaliza la velocidad en la inserción, borrado y actualización de datos. Me ha pasado que tras crear una vista con varios índices el funcionamiento de la aplicación empeoraba: ganaba dos segundos en la carga de datos pero perdía casi diez en la inserción.

¿En qué casos NO es recomendable crear índices sobre vistas?

  • Sistemas OLTP con muchas operaciones de escritura.
  • Bases de datos con múltiples actualizaciones.
  • Consultas que no requieran de joins o de funciones de agregado.
  • Consultas con agregación de datos con un alto grado de cardinalidad. (Es decir, que el conjunto de datos que devuelve la vista tenga prácticamente el mismo número de líneas que la tabla indizada)
  • Vistas que tienen conjuntos de resultados que son más grandes que los datos originales en las tablas base.

Aquí os dejo un artículo muy interesante, en inglés, sobre el tema. Ya tiene unos años pero los consejos son igualmente válidos.

SQL-Server: Anti-Join con NOT EXISTS()

Habíamos visto dos técnicas para hacer un anti-join en SQL-Server sin recurrir al NOT IN(): la primera con un left join y comprobando qué campos vienen a nulo y la segunda con el operado EXCEPT. ¿Hay una tercera opción? Sí, la hay: NOT EXISTS(). Como recordaréis ya habíamos visto por aquí que EXISTS() es una función de SLQ-Server muy bien optimizada, y en este caso podemos usarla también.

Vamos a poner un ejemplo: Tenemos la tabla Oficinas y tenemos la tabla Empleados. Las oficinas tienen un campo IdOficina que las identifica, los empleados también tiene un campo IdOficina que nos dicen en qué oficina trabajan. Queremos sacar en una consulta qué oficinas no tienen empleado. Veamos la consulta:

Select 
  o.IdOficina
from 
  Oficinas o
where 
  NOT EXISTS 
    (Select * from Empleados e where e.IdOficina = o.IdOficina)

¿Cual de los tres métodos es mejor? La recomendación es que le pegues un ojo al plan de ejecución para que veas cual tiene un menor coste.

SQL-Server: Hacer un anti-join con EXCEPT

El otro día os comentaba cómo hacer un anti-join en SQL-Server (a decir verdad con un método que valdría para cualquier SGBD), pero me dejé fuera otra forma de hacerlo en SQL-Server: con el operador EXCEPT.

La definción de EXCEPT vendría a ser la siguiente: Devuelve los valores distintos de la consulta situada a la izquierda del operando EXCEPT que no se devuelven desde la consulta derecha.

Vamos con un ejemplo: Tenemos la tabla Productos y tenemos la tabla Ventas, y el campo IdProducto existe en ambas, siendo la clave primaria de la tabla Productos y figurando como clave externa en tabla Ventas. Entonces ¿Podemos con EXCEPT sacar los Id de todos los Productos que no existen en la tabla Ventas? Podemos. Tal que así:

Select IdProducto from Productos
EXCEPT
Select IdProducto from Ventas

Al igual que ocurren con el operador UNION, el operador EXCEPT nos obliga a tener las mismas columnas, con tipos de datos compatibles, en cada una de las consultas.

SQL: cómo hacer un ANTI JOIN

Te habrá pasado más de una vez: necesitas sacar todos los valores de la Tabla1 que no aparezcan en la Tabla2. Es decir, la operación opuesta a un INNER JOIN. En muchos casos vemos que hay quien usa un NOT IN() como solución:

Nota: Asumimos que las tablas están bien formadas y que la Tabla1 se relaciona con la Tabla2 por medio de una clave externa (en el ejemplo será el campo IdClaveExterna en Tabla2 que está relacionado con el campo id de Tabla1)

SELECT * FROM Tabla1 
WHERE Tabla1.id NOT IN (SELECT IdClaveExterna FROM Tabla2)

Y esto está mal. Muy mal. Porque el IN() tiene un rendimiento muy bajo, como hemos visto en el pasado, y su negación pues todavía ofrece uno peor. Entonces ¿cómo lo hacemos? No tenemos una unión que sea ANTI JOIN, pero lo podemos resolver de la siguiente forma ya que tenemos un campo Id en cada tabla para cada fila sirviendo como clave primaria:

SELECT * FROM Tabla1 
LEFT JOIN Tabla2 ON Tabla1.id = Tabla2.idClaveExterna
WHERE Tabla2.id IS NULL

De esta forma cogemos todos los valores de la Tabla1 unidos a la Tabla2 por la clave externa, pero descartando de la consulta aquellos valores que nos devuelvan nulo el valor de la clave primaria de la Tabla2.