sábado, 2 de noviembre de 2024

GCP: funciones condicionales en BigQuery

 


El uso de funciones y sentencias condicionales es recurrente en el desarrollo de programas. Por ejemplo, para que el flujo se desvíe hacia cierto camino cuando así sea requerido. El lenguaje SQL que usa BigQuery no escapa de esa singularidad. 

Existen 6 sentencias o expresiones condicionales en BigQuery y éstas son:

  1. CASE expr.
  2. CASE.
  3. COALESCE.
  4. IF.
  5. IFNULL.
  6. NULLIF.

CASE expr

Compara la expresión dada con cada cláusula ``WHEN`` sucesiva y produce el primer resultado donde los valores son iguales.

Ejemplo:

DECLARE evaluacion STRING
SET evaluacion = 'sobresaliente';

SELECT CASE evaluacion  
       WHEN 'bueno' THEN 8
       WHEN 'excelente' THEN 9
       WHEN 'sobresaliente' THEN 10
       ELSE -1  as eval_result;

CASE

Evalúa la condición de cada cláusula ``WHEN`` sucesiva y produce el primer resultado donde la condición se evalúa como VERDADERO.

Ejemplo:

SELECT
  matematicas,
  historia,
  CASE
    WHEN matematicas > 9 THEN 'Sobresaliente'
    WHEN historia = 7 THEN 'Aceptable'
    ELSE 'Debes mejorar'
    END
    AS result_calf
FROM calificaciones

COALESCE

Produce el valor de la primera expresión no NULL, si la hay, de lo contrario es NULL.

Ejemplo:

SELECT COALESCE(NULL, 'Es un nulo', 'Es un valor no nulo') as resultado;

IF

Si una expresión se evalúa como VERDADERO, produce un resultado especificado; de lo contrario, produce la evaluación para un resultado else.

Ejemplo:

DECLARE x INT64
DECLARE y INT64;

SET x = 10;
SET y = 20;

SELECT
  x AS A,
  y AS B,
  IF(x < y, 'true', 'false') AS resultado;

IFNULL

Si una expresión se evalúa como NULL, produce un resultado especificado; de lo contrario, produce la expresión.

Ejemplo:

DECLARE valor INT64 DEFAULT 10;

SELECT IFNULL(NULL, 0) as result; -- NULL

SELECT IFNULL(valor, 0) as result; -- 10

NULLIF

Produce NULL si la primera expresión que coincide con otra se evalúa como VERDADERO; de lo contrario, devuelve la primera expresión.

Ejemplo:

DECLARE x INT64 DEFAULT 10;

SELECT NULLIF(0, 0) as resultado; -- NULL

SELECT NULLIF(x, 0) as resultado; -- 10

Más ejemplos en próximas entregas.

Enlaces:

https://cloud.google.com/bigquery/docs/reference/standard-sql/conditional_expressions

domingo, 20 de octubre de 2024

Un vistazo a la programación funcional

La Programación Funcional (Functional Programming)es un paradigma de programación declarativa (decir qué queremos, pero no cómo hacerlo) basado en el uso de funciones matemáticas donde:

  • Estaremos trabajando principalmente con funciones (el elemento principal para construir programas), evitaremos los datos mutables, así como el hecho de compartir estados entre funciones.
  • Y donde el valor generado por una función depende exclusivamente de los argumentos alimentados a la función.
  • Las funciones serán tratadas como ciudadanos de primera clase y podrán ser asignadas a variables además podrán ser utilizadas como entrada y salida de otras funciones.
  • Además, evitamos a toda costa los efectos secundarios que alteren el estado del programa u otros programas.
  • Ejemplos de lenguajes que soportan este paradigma son Haskell, Elixir, Erlang , Scala, y Clojure.

Características principales:

  1. Funciones puras: Las funciones siempre producen el mismo resultado para los mismos argumentos y no tienen efectos colaterales (no modifican variables globales ni realizan I/O directamente). 
  2.  Inmutabilidad: Los datos no se pueden modificar una vez creados. En lugar de cambiar valores, se crean nuevos valores. 
  3.  Funciones de orden superior: Las funciones pueden aceptar otras funciones como argumentos o devolver funciones. 
  4.  Composición de funciones: Las funciones se pueden combinar para crear otras más complejas, facilitando la reutilización de código. 
  5.  Evaluación perezosa: Las expresiones no se evalúan hasta que su resultado es necesario, optimizando el rendimiento en muchos casos.

Ventajas:

  1. Código más predecible y fácil de razonar gracias a la ausencia de efectos colaterales. 
  2. Facilidad para la concurrencia y el paralelismo, ya que no hay variables mutables que puedan causar conflictos.

Algunos conceptos clave de la Programación Funcional

  1. Funciones puras: Funciones que siempre producen el mismo resultado para los mismos argumentos. 
  2. Inmutabilidad: Los valores no pueden ser modificados una vez creados.
  3. Currificación: Funciones que pueden ser llamadas con menos argumentos de los que requieren originalmente.
  4. Composición de funciones: Encadenar funciones mediante el operador (.).
  5. Pattern matching: Hacer coincidir patrones en listas, tuplas, y otros datos estructurados.
  6. Guards y condicionales: Usar guards para control de flujo condicional.
  7. Recursión: La forma principal de control de iteraciones.

Ejemplo 1. Crear una función pura que nos sume dos números enteros. Este ejemplo lo haremos en Haskell.

suma.hs

suma :: Int -> Int -> Int
suma x y = x + y

main :: IO()
main = print (suma 8 3)

Como se puede ver, iniciamos con la delaración de tipos (Int). Definimos la función (suma) y en la d¿función principal (main) asignamos dos valores por default (8 y 3), lo cual nos dará como resultado 11.

Si solo queremos ejecutar el programa, abrimos una terminal y tecleamos lo siguiente:

runghc suma.hs

Si queremos compilar y crear un ejecutable, entonces:

ghc -o suma.exe suma.hs

Como la definición de una Función Pura indica, el resultado será el mismo cuando los argumentos son los mismos. Si invertimos el lugar del los valores (8, 3 por 3,8) el resultado seguirá siendo el mismo.

Aprender programación funcional se ha vuelto una "moda" que ya no solo implica el ámbito académico. Puesto que ya son muchos proyectos como la I.A. o Aprendizaje Automático que cada vez más requieren desarrolladores que dominen los principios de la matemática y, por ende, la programación funcional.

Enlaces:

https://codemonkeyjunior.blogspot.com/search?q=erlang
https://codemonkeyjunior.blogspot.com/search?q=elixir
https://emanuelpeg.blogspot.com/search?q=haskell

sábado, 19 de octubre de 2024

Terraform o Infraestructura cómo código

 

Según la Wikipedia, la Infraestructura como Código (Infrastructure as Code, en Inglés) es: el proceso de gestión y aprovisionamiento de centros de datos informáticos a través de archivos de definición legibles por máquina, en lugar de configuración de hardware físico o herramientas de configuración interactiva.

Básicamente:

  • Es la capacidad de aprovisionar y respaldar su infraestructura de computación a través de código en lugar de procesos y configuraciones manuales.  
  • Permite definir el estado deseado de su infraestructura sin incluir todos los pasos para llegar a ese estado.
  • Automatiza la administración de la infraestructura para que los desarrolladores puedan centrarse en crear y mejorar las aplicaciones en lugar de administrar los entornos.

Enfoques diferentes de la infraestructura como código

Declarativa

La IaC declarativa permite al desarrollador describir los recursos y la configuración que componen el estado final de un sistema deseado.

A continuación, la solución de IaC crea este sistema a partir del código de infraestructura. Esto hace que la IaC declarativa sea fácil de usar, siempre que el desarrollador sepa qué componentes y configuraciones necesita para ejecutar su aplicación.

Imperativa

La IaC imperativa permite al desarrollador describir todos los pasos para configurar los recursos y llegar al sistema y al estado de ejecución deseados.

Si bien no es tan sencillo escribir la IaC imperativa como la IaC declarativa, el enfoque imperativo se hace necesario en las implementaciones de infraestructuras complejas. Esto es especialmente cierto cuando el orden de los eventos es crítico.

¿Qué es Terraform?

Terraform es una herramienta de Infraestructura como Código (IaC) que permite definir, provisionar y gestionar infraestructura en la nube o en entornos locales mediante archivos de configuración.

Estos archivos, escritos en un lenguaje declarativo llamado HashiCorp Configuration Language (HCL), describen los recursos y servicios que se quieren desplegar, como servidores, redes, bases de datos, entre otros.

Terraform es capaz de interactuar con múltiples proveedores de servicios en la nube (como AWS, Azure, Google Cloud) y otras plataformas, facilitando la creación y modificación de infraestructuras complejas de forma eficiente.

Se relaciona con IaC porque permite automatizar y versionar la infraestructura de la misma manera que se gestiona el código de software, asegurando que las configuraciones sean reproducibles, auditables y escalables.

Instalando Terraform

En Linux:

Abrimos una terminal y escribimos estos comandos:


# Actualizar paquetes
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common

# Añadir repositorio oficial de HashiCorp:

wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list

# Instalar Terraform
sudo apt-get update && sudo apt-get install terraform

# Verificar instalación
terraform -v

Tendremos instalado Terraform en Linux.

En Mac OS:

Abrimos una terminal y escribimos estos comandos:


# Instala Terraform con Homebrew:
brew tap hashicorp/tap

brew install hashicorp/tap/terraform

terraform -v

Tendremos instalado Terraform en Mac OS.

En Windows:

Para esto es necesario contar con Chocolatey instalado en nuestras máquinas:

choco install terraform

Verificamos la instalación:

terraform -v

Tendremos Terraform instalado.

Ahora imaginemos que queremos crear una instancia de EC2 en AWS. Usaremos Terraform para lograrlo. La extensión del programa será *.tf

main.tf

# Especifica el proveedor de nube, en este caso AWS
provider "aws" {
  region = "us-east-1"  # Región donde se va a desplegar la infraestructura
}

# Definir una clave SSH para conectarse a la instancia
resource "aws_key_pair" "example" {
  key_name   = "example-key"
  public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3..."  # Llave pública SSH
}

# Crear una instancia de EC2 en AWS
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"  # Identificador de la AMI (Amazon Machine Image)
  instance_type = "t2.micro"  # Tipo de la instancia

  # Configurar la clave SSH para la instancia
  key_name = aws_key_pair.example.key_name

  tags = {
    Name = "Terraform Example Instance"  # Etiqueta para identificar la instancia
  }
}

# Salida para ver la IP pública de la instancia creada
output "instance_public_ip" {
  value = aws_instance.example.public_ip
}

1. Inicializamos el proyecto:

$ terraform init

2. Previsualizar los cambios (plan):

$ terraform plan

3. Aplicar cambios:

$ terraform apply

4. Destruir la infraestructura (cuando ya no sea necesaria):

$ terraform destroy

Hemos dado una breve explicación de lo que es IaC y cómo se relaciona con Terraform.

Enlaces:

https://chocolatey.org/
https://www.terraform.io/

PL/SQL: creando Stored Procedures (1era parte)

PL/SQL es un lenguaje de programación procedimental diseñado para operar en entornos Oracle.

Con este lenguaje podemos hacer:

  • Automatizar tareas complejas dentro de la base de datos mediante procedimientos y funciones.
  • Implementar reglas de negocio complejas con triggers y validaciones. 
  • Gestionar transacciones y manejar errores de manera robusta. 
  • Manipular conjuntos de datos utilizando cursores. 
  • Integrar lógica de negocios en aplicaciones que interactúan con bases de datos Oracle.

En esta ocasión veremos cómo crear Stored Procedures o procedimientos almacenados. Los cuales son procedimiento que pueden o no devolver algún valor (contrario a las funciones que siempre devuelven algún valor). Estos podrán, una vez que sean creado, ser invocados en tus scripts.

La sintaxis para crear un Stored Procedure es la siguiente:

-- Sintaxis para crear un Stored Procedure 
CREATE [OR REPLACE] PROCEDURE procedure_name
    [ (parameter [,parameter]) ]

IS
    [declaration_section]

BEGIN
    executable_section

[EXCEPTION
    exception_section]

END [procedure_name];

Para su invocación debemos anteponer la palabra ``CALL`` seguido del nombre.

CALL miprocedimiento();
CALL miprocedimiento(arg1, arg2, argN);

En un anterior post vimos cómo crear bloques PL/SQL. Un Stored procedure contiene bloques que harán determinada tarea que nosotros definamos.

BEGIN
  DBMS_OUTPUT.PUT_LINE('Hola desde PL/SQL');
END;

Ejemplo 1. Crear un Stored procedure para mandar un mensaje a pantalla.

hola.sql

CREATE OR REPLACE PROCEDURE hola 
IS 
  nombre VARCHAR2(6):='Thomas';
BEGIN 
  IF nombre IS NOT NULL THEN 
    dbms_output.put_line('Hola, '||nombre);
  END IF;
END;
/

Lo invocamos de está forma:

SET VERIFY OFF;
SET SERVEROUTPUT ON;

-- Invocar Stored procedure
CALL hola;

Ejemplo 2. Crear un Stored Procedure para ver la versión de Oracle instalada.

mi_proc.sql

CREATE OR REPLACE PROCEDURE mi_proc
    IS
    version_inst VARCHAR(200);
    consulta VARCHAR(200):='SELECT BANNER FROM v$version';    
BEGIN
    dbms_output.put_line('Version instalada: ');
    -- Ejecutamos consulta
    EXECUTE IMMEDIATE consulta INTO version_inst;
    dbms_output.put_line(version_inst);
END;
/

Lo invocamos:

SET VERIFY OFF;
SET SERVEROUTPUT ON;

CALL mi_proc;

Enlaces:

https://codemonkeyjunior.blogspot.com/2023/07/plsql-bloques.html
https://www.plsqltutorial.com/

GCP BigQuery: funciones de cadena y tiempo

En otras entregas hemos visto la creación de funciones y el uso de funciones propias de BigQuery. Ahora nos enfocaremos en las funciones de manejo de tiempo.

Funciones de tiempo

  • CURRENT_TIME
  • EXTRACT
  • FORMAT_TIME
  • PARSE_TIME
  • TIME
  • TIME_ADD
  • TIME_DIFF
  • TIME_SUB
  • TIME_TRUNC

Algunos ejemplos de su uso pueden ser:

SELECT CURRENT_TIME() as now;

Esto nos mostrará el tiempo actual.

BEGIN 

DECLARE T1 STRING;

SET T1 = "16:33:00";

SELECT EXTRACT(HOUR FROM TIME T1) as hour;

END;

Esto extraerá la hora de la variable ``STRING`` en formato de hora (hora:minutos:segundos).

BEGIN 

DECLARE T1 STRING;

SET T1 = "09:12:00";

SELECT PARSE_TIME("%I:%M:%S", T1);

END;

Esto convertirá la cadena ``STRING`` a una hora válida.

Como se puede ver, se ha creado una variable y se da el valor de una hora con sus minutos y segundos.

BEGIN 

DECLARE T1 STRING;
DECLARE T2 STRING;

SET T1 = "09:12:00";
SET T2 = "04:23:22";

SELECT PARSE_TIME("%I:%M:%S", T1);

SELECT PARSE_TIME("%T", T2);

END;

La función ``PARSE_TIME`` es muy útil a la hora de convertir cadenas a variables tipo ``TIME``. Si la cadena cumple el formato, la conversión será correcta.

Ahora veremos la función ``PARSE_TIME` que nos sirve para representar el tiempo (horas, minutos, segundos):

SELECT TIME(15, 30, 00) as time_hms;

Como se puede ver, las funciones de tiempo en BigQuery nos pueden ayudar para obtener los valores de fecha y hora con un formato adecuado.

Enlaces:

https://codemonkeyjunior.blogspot.com/2024/08/gcp-calculando-el-imc-con-bigquery.html

domingo, 13 de octubre de 2024

¿De qué trata esProc SPL?

esProc SPL es un lenguaje de procesamiento y cálculo de datos.

  • Se ejecuta como una base de datos de análisis o middleware.
  • Útil para cálculo y procesamiento de datos estructurados y semiestructurados. Ofrece un rendimiento superior y es ideal para tareas con uso intensivo de datos en el entorno impulsado por datos actual. 
  • Útil para trabajo por lotes sin conexión, consulta en línea.
  • Ni sistema SQL ni tecnología NoSQL. Trabaja directamente sobre los datos.
  • Con sintaxis SPL de creación propia, más concisa y eficiente SPL: Lenguaje de proceso estructurado.

En conclusión, esProc SPL está diseñado para el procesamiento avanzado de datos y se destaca en el manejo eficiente de conjuntos de datos masivos.

Los sitios oficiales del lenguaje son:

Si quieres aprenderlo, puedes revisar la documentación oficial:

https://www.scudata.com/html/SPL-programming-book.html

Al iniciar la aplicación, se abre un grid similar a las hojas de Excel. Es aquí donde se escribe el código:

Escribimos el código o instrucciones de manera similar a lo que se hace en Excel:

=2*1.5
=1*(2+3)
=65536*65536*65536*65536
=1*(2-3*(4+5))

Se pueden operar con tipos de datos Integer, Float, Long, etc. Además de también realizar operaciones booleanas (que dan resultados TRUE o FALSE). Hacer uso de sentencias de control para los bucles o condiciones a cumplir en el programa (for, ).

=if(x>0,x,-x)
=if(x>y,x,y)

!true = false
!false = true

=A1*A1*A1
>A1=B1

for 20

=[3,9,0,2,2.3,9.8]

if B1<=100

Podemos concluir en que esProc SPL es un lenguaje de script para procesamiento de datos, con funciones de biblioteca ricas y bien diseñadas y una sintaxis poderosa, que puede ejecutarse en un programa Java a través de la interfaz JDBC y computarse de forma independiente.

Continuaremos en próximas entregas.

Enlaces:

https://dev.to/bigsondev/10-programming-languages-worth-learning-in-2024-afa
https://github.com/SPLWare/esProc
https://www.scudata.com/
https://www.reddit.com/r/esProc_SPL/
https://www.scudata.com/html/SPL-programming-book.html

sábado, 5 de octubre de 2024

Gleam en ejemplos

Continuamos con el tema de Gleam, un lenguaje que corre sobre la máquina virtual de Erlang (BEAM). Similar a Elixir en algunos aspectos.

Si quieres programar usando este lenguaje y además usas VsCode como editor, existe un plugin que podrás instalar:

https://marketplace.visualstudio.com/items?itemName=Gleam.gleam

Te ayudará en el resaltado de estilo, formato, definición y autocompletado.

Recordemos cómo crear un proyecto en Gleam:

gleam new proyecto

Nos ubicamos en el directorio creado:

cd proyecto

Podemos usar VsCode. Abrimos una terminal y tecleamos:

code .

Esto abrirá el editor de código.

Ejemplo 1. Crear una función que mande un saludo.

La sintaxis para crear una función es la siguiente:

pub fn nombre_funcion() {
  // Cuerpo del procedimiento o función
}

Nuestra función será esta:

pub fn saludo() {
  io.println("\t Hola, mundo desde Gleam")
}

La invocamos desde el método main del programa principal.

proyecto.gleam

import gleam/io

pub fn main() {
  saludo()
}

pub fn saludo() {
  io.println("\t Hola, mundo desde Gleam")
}

Construimos y ejecutamos:

gleam build
gleam run

Salida:

        Hola, mundo desde Gleam

Ejemplo 2. Crear una función que calcula el factorial de un número.

Teniendo el siguiente pseudo código:

numero = 5
IF numero = 0 THEN
   result = 1
IF ELSE numero = 1 THEN
   result = 1
ELSE 
   result = numero * FACTORIAL(numero - 1)

La función en Gleam quedaría de tal modo:

pub fn factorial(x: Int) -> Int {
  case x {
    0 -> 1
    1 -> 1
    _ -> x * factorial(x - 1)
  }
}

La invocamos de esta manera:

import gleam/io
import gleam/int

pub fn main() {
  io.println("\t===== Factorial en Gleam =====")
  io.println("El factorial de 5: ")
  io.debug(factorial(5))
  io.println("El factorial de 7: ")
  io.debug(factorial(7))
}

Ejemplo 3. Crear una función anónima que sume dos número enteros.

fn suma(a: Int, b: Int) -> Int {
  a + b
}

Y la invocamos de la siguiente forma:

import gleam/io
import gleam/int


pub fn main() {
  io.println("\t===== Sumando en Gleam =====")
  let add = suma(3, 4)
  io.println("Suma (3,4) es: ")
  io.debug(add)
}

Este post se irá actualizando para agregar más ejemplos.

Enlaces:

https://codemonkeyjunior.blogspot.com/2024/03/conociendo-gleam-un-lenguaje-que-corre.html
https://emanuelpeg.blogspot.com/search?q=gleam

sábado, 7 de septiembre de 2024

Crystal, un lenguaje de programación similar a Ruby

Crystal es un digno "copycat" del lenguje de programación Ruby. Su sintaxis es más que similar.

cadena = "Codemonkey Junior"
puts cadena

Y es que escribir unas cuantas líneas en este lenguaje nos recuerda a Ruby. Crystal es de esos lenguajes que deberías aprender o echar un vistazo, al menos por curiosidad.

Para instalarlo deberás entrar a este sitio y escoger la instalación de acuerdo a tu SO:

https://crystal-lang.org/install/

Una vez instalado, abre una terminal y teclea:

crystal --version

Eso listará la versión instalada.

Empezaremos con el clásico programa de "Hola, mundo".

holamundo.cr

puts "Hola, mundo!!"

Ejecutamos:

crystal holamundo.cr

Salida:

Hola, mundo!!

Sigamos con otro ejemplo. Mostremos algunas variables en Crystal.

variables.cr

# Variables en Crystal
entero = 0
caracter = '\u0032'
booleano = true
real = 9.32
 
puts "#{entero}"
puts "#{caracter}"
puts "#{real}"
 
if booleano
    puts "Es verdadero"
end

Ejecutar:

crystal variables.cr

Salida:

0
2
9.32
Es verdadero

¡Hemos creado nuestros primeros programas en Crystal!

Continuaremos con este tema más adelante.

Enlaces:

https://crystal-lang.org/

sábado, 31 de agosto de 2024

Sinatra, un DSL útil para crear sitios web de manera rápida

Sinatra es una herramienta que toma su nombre del famoso cantante estadounidense. Similar a otras herramientas como Flask (salvando las diferencias, claro esta). Con la peculiaridad que esta diseñado para el lenguaje de programación Ruby.

¿Qué haremos?

  1. Instalar Ruby.
  2. Instalar Sinatra.
  3. Crear un proyecto sencillo con Sinatra.

Una vez instalado Ruby podemos comprobar la instalación:

ruby --version

Instalamos Sinatra y Rackup:

gem install sinatra
gem install rackup

También podemos instalar Puma (opcional):

gem install puma

Para ver nuestras "gemas" instaladas, basta con ubicarnos en esta carpeta (gem):

C:\Users\HP\.local\share\gem\ruby\3.3.0\gems

Creamos un programa llamado ``myapp.rb``. El cual tendrá lo siguiente:

# myapp.rb
require 'sinatra'

get '/' do
  'Hola, mundo!'
end

Ejecutamos la aplicación:

ruby myapp.rb

Si todo es correcto, veremos un mensaje de "Hola, mundo!" en la dirección http://[::1]:4567 o http://localhost:4567

¡Hemos creado nuestra primera aplicación con Sinatra!

En próximas entregas continuaremos con este tema.

Enlaces:

https://sinatrarb.com/
https://www.ruby-lang.org/es/
https://rubyinstaller.org/
https://crguezl.github.io/apuntes-ruby/node409.html

sábado, 10 de agosto de 2024

GCP: Calculando el IMC con BigQuery

 


En esta ocasión veremos cómo crear una función y procedimiento almacenado para el cálculo del IMC (Índice de Masa Corporal), necesitaremos lo siguiente:

  1. La fórmula para el cálculo del IMC.
  2. Crear una función para calcularlo.
  3. Crear un procedimiento almacenado (stored procedure) para usar la función.
  4. Crear un bloque de código en BigQuery para invocar el procedimiento. 

Tenemos la fórmula:

-- Obtener IMC
IMC = p/(t*t)

Donde:
p= peso
t= talla o estatura
imc = el índice de masa corporal

Creando función para calcular el IMC:

CREATE OR REPLACE FUNCTION `myproject.dataset.imcCalculo`(peso NUMERIC, talla NUMERIC)
RETURNS NUMERIC AS(
  (peso/(talla*talla))
);

Básicamente es una operación sencilla que solo incluye una multiplicación de la talla y la división del peso.

Creando procedimiento almacenado para invocar la función:

CREATE OR REPLACE PROCEDURE `myproject.dataset.getIMC`(peso NUMERIC, talla NUMERIC, OUT msg STRING)
BEGIN 
  DECLARE imc NUMERIC DEFAULT 0.0;
  
  set msg = 'Iniciamos calculo. ';
  SET imc = (SELECT `myproject.dataset.imcCalculo`(peso, talla));
  set msg = concat(msg, 'El IMC es: ', imc, '. Resultado: ');
  set msg = concat(msg, (  
    CASE imc
    WHEN imc<=16.0 OR imc<=16.99 THEN 'Delgadez moderada.'
    WHEN imc<=17.0 OR imc<=18.49 THEN 'Delgadez aceptable.'
    WHEN imc<=18.50 OR imc<=24.99 THEN 'Peso normal.'
    WHEN imc<=25.0 OR imc<=29.99 THEN 'Sobrepeso.'
    WHEN imc<=30.0 OR imc<=34.99 THEN 'Obeso tipo I.'
    WHEN imc<=35.0 OR imc<=40.0 THEN 'Obeso tipo II.'
    ELSE 'No existe clasificacion'
    END)
  );
  
  
  SELECT msg;
  

END;

En el procedimiento almacenado incluimos un mensaje de salida (OUT msg STRING) el cual podrá ser consultado al finalizar el llamado. Este contendrá el cálculo del IMC y el diagnóstico final (peso normal, sobrepeso, etc.).

Creando bloque de BigQuery para invocar procedimiento almacenado:

-- Obtener IMC
BEGIN  
DECLARE peso NUMERIC DEFAULT 56.0;
DECLARE talla NUMERIC DEFAULT 1.65;
DECLARE msg STRING DEFAULT 'Inicio';

CALL `myproject.dataset.getIMC`(peso, talla, msg);
SELECT msg;

END;

Usar un bloque nos ayuda a disminuir una cantidad "grosera" de sentencias.

El resultado de la operación nos dará como resultado: 20.5693. La salida será:

Iniciamos calculo. El IMC es:  20.569329. Resultado: Peso normal.

Crear funciones y procedimientos almacenados es algo muy útil y que nos ahorrará trabajo.

Enlaces:

https://cloud.google.com/bigquery/docs/reference/standard-sql/conditional_expressions
https://codemonkeyjunior.blogspot.com/2024/08/gcp-cargar-y-exportar-datos-en-bigquery.html

https://lineadecodigo.com/java/calcular-el-indice-de-masa-corporal-con-java/
https://codemonkeyjunior.blogspot.com/2013/05/programando-en-ceylon-no1_13.html

sábado, 3 de agosto de 2024

GCP: Cargar y exportar datos en BigQuery


GCP BigQuery nos permite tanto cargar como exportar datos. Los formatos de los archivos pueden ser TXT o CSV generalmente.

Si queremos exportar datos de una tabla a un archivo CSV podríamos hacer los siguiente.

Abrimos la consola de GCP y en el editor de consultas colocamos:

EXPORT DATA
  OPTIONS (
    uri = 'gs://bucket/folder/pesos*.csv',
    format = 'CSV',
    overwrite = true,
    header = true,
    field_delimiter = ';')
AS (
  SELECT fecha, valor
  FROM mydataset.pesos
  ORDER BY fecha
);

Como se puede ver:

  1. Colocamos la ubicación de nuestro Bucket.
  2. Seteamos el formato del archivo, en este caso será un CSV.
  3. El archivo será sobreescrito.
  4. El delimitardor será un punto y coma (;).

Una vez que el comando es ejecutado desde el editor de consultas GCP, debemos uicarnos en el directorio y descargar el archivo CSV generado.

Si queremos complicarnos la vida, podríamos crear un programa en Java que haga exactamente los mismo.

ExtractTableToCsv.java

import com.google.cloud.RetryOption;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.Table;
import com.google.cloud.bigquery.TableId;
import org.threeten.bp.Duration;

public class ExtractTableToCsv {

  public static void runExtractTableToCsv() {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "bigquery-public-data";
    String datasetName = "samples";
    String tableName = "shakespeare";
    String bucketName = "my-bucket";
    String destinationUri = "gs://" + bucketName + "/path/to/file";
    // For more information on export formats available see:
    // https://cloud.google.com/bigquery/docs/exporting-data#export_formats_and_compression_types
    // For more information on Job see:
    // https://googleapis.dev/java/google-cloud-clients/latest/index.html?com/google/cloud/bigquery/package-summary.html

    String dataFormat = "CSV";
    extractTableToCsv(projectId, datasetName, tableName, destinationUri, dataFormat);
  }

  // Exports datasetName:tableName to destinationUri as raw CSV
  public static void extractTableToCsv(
      String projectId,
      String datasetName,
      String tableName,
      String destinationUri,
      String dataFormat) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      TableId tableId = TableId.of(projectId, datasetName, tableName);
      Table table = bigquery.getTable(tableId);

      Job job = table.extract(dataFormat, destinationUri);

      // Blocks until this job completes its execution, either failing or succeeding.
      Job completedJob =
          job.waitFor(
              RetryOption.initialRetryDelay(Duration.ofSeconds(1)),
              RetryOption.totalTimeout(Duration.ofMinutes(3)));
      if (completedJob == null) {
        System.out.println("Job not executed since it no longer exists.");
        return;
      } else if (completedJob.getStatus().getError() != null) {
        System.out.println(
            "BigQuery was unable to extract due to an error: \n" + job.getStatus().getError());
        return;
      }
      System.out.println(
          "Table export successful. Check in GCS bucket for the " + dataFormat + " file.");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Table extraction job was interrupted. \n" + e.toString());
    }
  }
}

Ahora, ¿si queremos cargar un archivo a una determinada tabla?

Procedemos a escribir la siguiente instrucción en el editor de consultas de GCP:

LOAD DATA INTO mydataset.pesos FROM FILES(
  format = 'CSV',
  uri = ['gs://bucket/folder/123.csv','gs://bucket/folder/456.csv']
);

Donde:

  1. Definimos el formato de los archivos a cargar, en este caso son CSV.
  2. Colocamos la ubicación de los archivos de datos a cargar en la tabla (pesos).

Nota: El archivo CSV debe contener campos que concuerden con los de la tabla. En caso contrario, habrá errores a la hora de la carga.

Si queremos complicarnos la vida, podríamos crear un programa en Java que haga exactamente los mismo.

LoadCsvFromGcs.java

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.CsvOptions;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.LoadJobConfiguration;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardSQLTypeName;
import com.google.cloud.bigquery.TableId;

// Sample to load CSV data from Cloud Storage into a new BigQuery table
public class LoadCsvFromGcs {

  public static void runLoadCsvFromGcs() throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    String sourceUri = "gs://cloud-samples-data/bigquery/us-states/us-states.csv";
    Schema schema =
        Schema.of(
            Field.of("name", StandardSQLTypeName.STRING),
            Field.of("post_abbr", StandardSQLTypeName.STRING));
    loadCsvFromGcs(datasetName, tableName, sourceUri, schema);
  }

  public static void loadCsvFromGcs(
      String datasetName, String tableName, String sourceUri, Schema schema) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      // Skip header row in the file.
      CsvOptions csvOptions = CsvOptions.newBuilder().setSkipLeadingRows(1).build();

      TableId tableId = TableId.of(datasetName, tableName);
      LoadJobConfiguration loadConfig =
          LoadJobConfiguration.newBuilder(tableId, sourceUri, csvOptions).setSchema(schema).build();

      // Load data from a GCS CSV file into the table
      Job job = bigquery.create(JobInfo.of(loadConfig));
      // Blocks until this load table job completes its execution, either failing or succeeding.
      job = job.waitFor();
      if (job.isDone()) {
        System.out.println("CSV from GCS successfully added during load append job");
      } else {
        System.out.println(
            "BigQuery was unable to load into the table due to an error:"
                + job.getStatus().getError());
      }
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Column not added during load append \n" + e.toString());
    }
  }
}

Nota: El código se tomó de la página oficial de GCP. Tu lo puedes editar a tu conveniencia.

Hemos visto como cargar y exportar datos a tablas en BigQuery.

Enlaces:

https://cloud.google.com/bigquery/docs/exporting-data
https://cloud.google.com/bigquery/docs/loading-data-cloud-storage-csv