Archivo del Autor: PabloE

Oracle 12.2 Cool New Features

En el último Oracle Open World se ha anunciado el lanzamiento de Oracle 12cR2 (o 12.2). En el siguiente artículo se repasan algunas de las novedades más importantes: Oracle 12.2 Cool New Features

  • Partitioning
    • Alter table to partitioned table
    • Create table for exchange
  • In-Memory
    • Standby Database: In-Memory option
    • Dynamic resizing
    • Fast start
  • Security
    • Online encryption and re-key operations
    • Internal tablespace encryption
    • DB vault simulation
  • Dictionary
    • Long identifiers
  • PDB
    • Resource management
    • Hot clone
    • Local undo
    • Flashback
    • Characterset
  • Others
    • Index Monitoring
    • Materialized Views – real time refresh
    • External Tables – partitions

Select sobre colecciones PL/SQL correlacionadas

Oracle permite acceder a los valores de colecciones PL/SQL desde sentencias SQL. Esta propiedad del comando SELECT se llama table_collection_expression y muestra el contenido de una colección como si de una tabla se tratara.

Para que el proceso funcione correctamente es necesario que la colección esté declarada en el esquema, no dentro de un paquete:

-- Create PL/SQL collection
create or replace type ty_number is table of number;

-- Select from one PL/SQL collection
select * from table(ty_number(10,20,30,50,40));

La sentencia daría como resultado:

COLUMN_VALUE
------------
10
20
30
50
40

Esta propiedad puede resultarnos muy útil cuando estamos programando en PL/SQL y, por ejemplo, necesitamos extraer datos de una consulta a través de un proceso bulk collection y compararlos con registros de otras tablas.

Pero, ¿qué ocurre si necesitamos cruzar datos de dos colecciones PL/SQL y datos de tablas? ¿Cómo vamos a correlacionar los elementos de varias colecciones entre sí? En estos casos podemos recurrir a una sentencia join en combinación con la cláusula connect by level para generar los índices que nos permitirán recorrer las colecciones:

-- Select from two correlated PL/SQL collections
select coll_index, coll_1_value, coll_2_value
from (select level coll_index from dual connect by level <= 5) gen_idx -- Generate index for iterate collections
     join (select rownum rn, column_value coll_1_value from table(ty_number(10,20,30,50,40))) coll_1 on gen_idx.coll_index = coll_1.rn -- Collection 1
     join (select rownum rn, column_value coll_2_value from table(ty_number(11,21,31,51,41))) coll_2 on gen_idx.coll_index = coll_2.rn; -- Collection 2

La ejecución de la sentencia produce el siguiente resultado:

COLL_INDEX	COLL_1_VALUE	COLL_2_VALUE
----------	------------	------------
1		10		11
2		20		21
3		30		31
4		50		51
5		40		41

Como puede apreciarse al fijarnos en las filas 4 y 5, los elementos de las colecciones mantienen el orden original y la correlación entre sus elementos.

Oracle Developer Gateway banner

Oracle Developer Gateway

Oracle ha reunido en una web todo el material relacionado con el desarrollo de software: Oracle Developer Gateway

Select random rows

Para seleccionar una o varias filas de una tabla de manera aleatoria existen distintos enfoques. En este ejemplo se intenta obtener una fila de la tabla EMP tomando una muestra del 25% de los registros totales sobre el que posteriormente se aplica una ordenación utilizando la función DBMS_RANDOM.random. De esta forma podemos aplicar una ordenación aleatoria sobre los registros de la tabla evitando el alto coste de ejecutar la función random en tablas que sean muy grandes.

-- Select 1 random row from EMP table
select *
from ( select *
    from emp sample(25) -- 25% total rows
    order by dbms_random.random)
where rownum = 1;

El resultado:

EMPNO	ENAME	JOB	MGR	HIREDATE	SAL	COMM	DEPTNO
7698	BLAKE	MANAGER	7839	01-MAY-81	2850	-	30

GitHub: Oracle Database Sample Schemas

A través de GitHub – oracle/db-sample-schemas Oracle pone a disposición de la comunidad de desarrolladores y diseñadores de bases de datos los scripts para generar los siguientes schemas:

  • HR: Human Resources
  • OE: Order Entry
  • PM: Product Media
  • IX: Information Exchange
  • SH: Sales History
  • BI: Business Intelligence

Tratamiento de NIF españoles

Una expresión regular para tratar los NIF españoles eliminando todos los caracteres que no sean números o letras. Además, comprueba el tamaño del NIF para incluir el código de país (identificador fiscal comunitario) si fuera necesario:

select result1 ORIGINAL_TAXID, 
    upper(
        regexp_replace( 
            regexp_replace(result1, '[^[:alnum:]]', ''), -- Remove non-digit and non-alphabetic characters 
            '^([[:alnum:]]{1}[[:digit:]]{1})([[:alnum:]]{7})$', -- Identify spanish NIFs without country code 
            'ES\1\2')) CLEAN_AND_COMPLETE_TAXID -- Add spanish country code 
from ( 
    WITH test AS 
     (SELECT 'ESA45678901,B23456789,GB3456789,12345678L,B234567890123,ES-A45678901,B.23456789,GB3::456789,B234_567_890123' col1 FROM dual) 
    SELECT regexp_substr(col1, '[^,]+', 1, rownum) result1 
      FROM test 
    CONNECT BY LEVEL <= regexp_count(col1, ',') + 1 
);

El resultado es:

ORIGINAL_TAXID	CLEAN_AND_COMPLETE_TAXID
--------------- ------------------------
ESA45678901	ESA45678901
B23456789	ESB23456789
GB3456789	GB3456789
12345678L	ES12345678L
B234567890123	B234567890123
ES-A45678901	ESA45678901
B.23456789	ESB23456789
GB3::456789	GB3456789
B234_567_890123	B234567890123

UUID en forma canónica

Cómo generar de un «Universally Unique Identifier» (UUID) desde una select y convertirlo a su forma canónica «8-4-4-4-12»:

select lower(
        regexp_replace(
           rawtohex(sys_guid())
           ,'([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})'
           ,'\1-\2-\3-\4-\5')) GUID_canonical_format
from dual;

Resultado:

GUID_CANONICAL_FORMAT
------------------------------------
34266296-4de0-26df-e053-0100007fd523

El análisis de datos y la interpretación de resultados

Oracle DBInsights Forum

El pasado miércoles 20 de abril se celebró en Madrid el Oracle DBInsights Forum. La mañana se dedicó casi de manera íntegra al análisis de datos o Data Science. Pau Agulló, director de Kernel Analytics, presentó tres casos prácticos en los que se habían empleado diferentes técnicas de análisis:

  • Mejora de la relevancia para personalizar las ofertas de una empresa de ventas flash.
  • Predicción de la demanda y gestión de stock en la gran distribución.
  • Expansión óptima de red: cómo mejorar la planificación de las inversiones en la red canalizada de una empresa de gas.

Los tres casos resultaron de gran interés y mostraban cómo el análisis de datos podía aprovechar la información disponible para mejorar aspectos muy distintos del negocio o las inversiones de estas empresas. Pero a mi me llamó especialmente la atención la primera de ellas dedicada a la mejora de la relevancia. Pau Agulló nos explicó los pasos que siguieron en el desarrollo de este proyecto desde el punto de vista del análisis de datos y cómo lograron aumentar las ventas a través de la personalización de la oferta.

Vamos a sintetizar los puntos más importantes de su presentación aprovechando la metodología que proponen Roger D. Peng y Elizabeth Matsui en su libro The Art of Data Science y las cinco etapas del análisis de datos:

Art of Data Science

En el libro The Art of Data Science se describe la metodología que subyace a todo proyecto en Data Science, siempre en opinión de sus autores, y que definen como una iteración de cinco etapas:

  1. Definición de las preguntas a resolver.
  2. Exploración de datos.
  3. Modelado de datos.
  4. Interpretación de los resultados.
  5. Comunicación de los resultados.

Cada una de estas cinco etapas se centra en un aspecto determinado del análisis. Pero al mismo tiempo, es importante revisar continuamente los resultados obtenidos en etapas anteriores para verificar si se mantiene la línea prevista o se ha producido alguna desviación que debamos revisar. Este aspecto del análisis es el más importante: la revisión continua de los resultados con respecto a las expectativas. En todo proyecto de análisis de datos, a medida que se va profundizando, se descubren nuevos enfoques que, no con poca frecuencia, nos empujan a replantearnos alguna de las etapas anteriores o incluso el propio marco de trabajo. Los autores del libro llaman a esta revisión continua Epicycles of Analysis y lo dividen en tres bloques:

  • Definición de expectativas.
  • Recopilación de datos.
  • Cotejo de las expectativas con los datos recopilados.

Estos epiciclos se deben repetir en cada una de las cinco grandes etapas del análisis.

La presentación que hizo Pau Agulló en el Oracle DBInsights Forum siguió perfectamente este modelo de trabajo:

1. Definición de las preguntas a resolver

La pregunta que definía el proyecto sobre mejora de la relevancia era la siguiente:

¿Cómo mejorar las recomendaciones que la empresa de ventas flash enviaba todos los días a sus usuarios por correo electrónico?

2. Exploración de datos

Esta etapa se centra en evaluar la información disponible y refinar la pregunta inicial para evitar resultados ambiguos, sesgos o detectar la necesidad de recopilar nuevos datos.

En el caso presentado, lo habitual es centrarse en los datos obtenidos a través de las siguientes fuentes:

  1. Ventas: es la fuente más importante en cuanto a calidad del dato pero la menos frecuente por su cantidad.
  2. Carritos abandonados.
  3. Clicks en boletines de noticias.
  4. Navegación por la web: la fuente menos relevante por su calidad pero más abundante en cantidad.

3. Modelado de datos

En el modelado de datos se busca una serie de procesos y algoritmos que se puedan estandarizar y que nos permitan tratar los datos disponibles para mejorar la comprensión de los mismos. En otras palabras, establecer un protocolo para tratar los datos disponibles y extraer de ellos la mayor información relevante posible: convertir los datos en conocimiento.

El objetivo principal en los sistemas de mejora de la relevancia es reducir el tiempo necesario para que un cliente encuentre el producto que le interesa. Para lograrlo se pueden utilizar diferentes vías complementarias entre sí:

  • Cálculo de afinidad: comparación entre elecciones de distintos clientes.
  • Diversificación de oferta: productos vinculados que pertenezcan a otras categorías.
  • Objetivos del negocio: mejorar el volumen de ventas o el margen en cada operación.

En el caso expuesto, una vez establecido el modelo de datos, se hizo un reparto de los envíos de correos electrónicos entre las recomendaciones habituales y las nuevas recomendaciones personalizadas mediante los criterios del modelo desarrollado. Esto permitió completar el epiciclo de análisis en el modelado de datos mediante el cotejo de las expectativas con los datos recopilados en cada uno de los escenarios.

4. Interpretación de los resultados

Los autores del libro The Art of Data Science introducen el capítulo sobre la interpretación de resultados advirtiendo de que esta tarea, en realidad, se pone en práctica en todas y cada una de las etapas del análisis de datos. Es inevitable que las personas involucradas en un proyecto de análisis interpreten los distintos resultados parciales que se obtiene a medida que se avanza en el trabajo. Al mismo tiempo, reivindican la importancia de dedicar un espacio exclusivo para la interpretación, una vez tratados los datos, creados los modelos y cotejados los resultados para sacar las conclusiones finales.

En el proyecto de mejora de la relevancia se comparó el resultado de ventas que provenían de los boletines de ofertas generales y las ventas provenientes de los nuevos boletines elaborados con el modelo de datos. Se buscaba determinar en qué medida las diferencias observadas respondían a la personalización de la oferta o a factores ajenos al modelo (por ejemplo, sesgos en la muestra de usuarios escogida para la prueba).

5. Comunicación de los resultados

El resultado final fue muy satisfactorio para el modelo de datos que se había desarrollado: lograron mejoras en las ventas a través de una selección personalizada de las ofertas a destacar. Estos resultados fueron presentados en distintos ámbitos, como es natural. Entre otros, en el propio Oracle DBInsights Forum.

El recomendador de películas y la interpretación de resultados

En una charla posterior se comentó la siguiente anécdota:

«Ayer por la noche estaba en el salón buscando una película para ver y escogí una de las recomendadas. Al cabo de veinte minutos de película ya no aguantaba más. Era terrible. Así que la paré, me fui a la cocina a beber algo y, a la vuelta, me puse otra película.

Ahora caigo en que el algoritmo de recomendación habrá etiquetado la primera película como visionada y como un acierto del sistema de recomendación. Lo normal -nos explicó- es que a los diez minutos de reproducción una película se considere como visionada. Y lo que en realidad ocurrió es que me pareció una película espantosa y por eso la dejé de ver.»

Esta pequeña historia nos sirvió para comentar lo difícil que resulta en algunos casos interpretar unos hechos a través de las trazas que registramos en los sistemas informáticos. Y se plantearon muchas hipótesis que podrían haber explicado esta misma cadena de sucesos. Vamos a exponer alguna de ellas:

En primer lugar, los datos sobre los que trabajamos fueron:

  • Un usuario de una plataforma de vídeos a la carta selecciona una película recomendada y empieza a verla.
  • A los 20 minutos se interrumpe la reproducción.
  • 5 minutos más tarde empieza la reproducción de otra película.

Estos datos, por supuesto, encajaban perfectamente en lo que realmente sucedió: el usuario dejó de ver la película para ver otra diferente. Esto podría indicar claramente que la primera elección no le gustó. Especialmente porque no interrumpió la visualización sin más, como si hubiera tenido que atender algo urgente que le impidiera seguir con la película. Si no que al cabo de 5 minutos inició una película distinta. Parece muy claro, ¿verdad?

Pero en seguida surgió una explicación alternativa: ¿y si no fue la misma persona la que inició la reproducción de la segunda película? Atendiendo solo a los datos recogidos, también cabe la posibilidad de que la primera persona se puso una película pero tuvo que interrumpirla por algo más urgente que le impidió seguir viéndola. A los 5 minutos, una persona distinta aprovechó que la televisión estaba libre para poner una nueva película.

En la conversación fueron apareciendo, poco a poco, otros relatos que incluían los mismos puntos involucrados en situaciones muy diferentes y, por lo tanto, interpretaciones también muy variadas.

En definitiva, solo se trataba de un recomendador de películas automático. Incluso nuestros mejores amigos, que conocen bien nuestros gustos, se equivocan en algunas recomendaciones.

HEXTOBLOB

Implementación de la función HEXTORAW para dar soporte a CLOBS:

create or replace
procedure hextoblob(
                    src_clob  in       clob,
                    dest_blob in out   nocopy blob
				   )
is
    v_pos    number := 1;
    v_amount number := 1024;
    v_buffer varchar2(1024);
    v_raw    raw(2048);
begin

    while v_pos < dbms_lob.getlength(src_clob)
    loop
        dbms_lob.read(
            lob_loc => src_clob, 
            amount  => v_amount, 
            offset  => v_pos, 
            buffer  => v_buffer);
        
        v_raw := hextoraw(v_buffer);

        dbms_lob.writeappend(
            lob_loc => dest_blob, 
            amount  => utl_raw.length(v_raw), 
            buffer  => v_raw);
        
        v_pos := v_pos + v_amount;
    end loop;
    
end hextoblob;

Para probar el procedimiento podemos ejecutar el siguinte código:

declare
  cl_test   clob := '4041424344';
  bl_result blob;
begin

  dbms_lob.createtemporary(
    lob_loc => bl_result,
    cache   => false,
    dur     => dbms_lob.call);

  hextoblob(
    src_clob  => cl_test,
    dest_blob => bl_result);

  dbms_output.put_line('Result: '||
                        utl_raw.cast_to_varchar2( bl_result ));

  dbms_lob.freetemporary( bl_result );

end;

El resultado debe ser:

Result: @ABCD