Webcast – Escribiendo código T-SQL eficientemente


En el presente post, les hago entrega del webcast que realize para la comunidad SQL PASS Latam – Caracas Chapter, conjuntamente con mi compañero de SQL PASS Latam, su director Jesús Gil titulado “Escribiendo código T-SQL eficientemente”.

En el siguiente enlace, podrán descargar tanto la presentación en formato .pptx así como la grabación de manera gratuita:

https://skydrive.live.com/?cid=cfe236f1f894452b&id=CFE236F1F894452B%21122&authkey=!ADAjwja_cGEcGVU#

Hasta una próxima entrega, Winking smile.

Serie “Análisis de datos”: Conceptos Generales de MDX (Parte 2).


Dando continuidad a la serie “Analisis de datos”, en esta entrega, culminare los últimos tópicos a tratar, referentes a los conceptos básicos del lenguaje MDX como lo son:

  • Celdas (Cells)
  • Tuplas (Tuples)
  • Conjunto de datos (Sets)

CELDAS

El siguiente ejemplo en el gráfico No. 1, podemos observar tres (3) caras de un cubo. La cara que se encuentre de frente, se encuentra dividido en 16 cuadrados, y cada cuadrado tiene un número. Supongamos que el número dentro de cada cuadrado es una medida (Como por ejemplo en el mismo “Internet Sales Amount”). Si vemos las caras visibles restantes del este cubo, se puede ver que cada cuadro que se analiza en dicha cara frontal es en realidad un cubo pequeño, cierto.

Gráfico No. 1

El “Cubito” de la esquina superior derecha podemos observar que contiene el número 1134, este mismo número se representa en los otros lados también.

El proposito mio en este enfasis es demostrarles que este cubo más pequeño se conoce como “Celda”. Las Celdas contienen los valores de los datos de todas Las Medidas del cubo. Si el valor de datos para una medida dentro de una celda no se encuentra disponible, el valor de dicha medida correspondiente es ‘Nulo’.

Ahora, el número de celdas dentro de un cubo depende del número de jerarquías dentro de cada Dimensión y el número de Miembros en cada Jerarquía, lo ven.

Hagamos una análogia, la similitud a un espacio de coordenadas tridimensional, donde cada punto esta representado por un valor de coordenada ‘X’, ‘Y’ y ‘Z’, cada Celda dentro de un cubo esta representada por los miembros de dimensión. En el siguiente gráfico, se pueden apreciar tres (3) dimensiones:

  • Productos (Product)
  • Clientes (Customer)
  • Tiempo (Date)

Grafico 2

Gráfico No. 2

Supongamos que cada una de estas Dimensiones tienen exactamente una Jerarquía, por tanto, nosotros podemos ver que la Línea de Productos cuenta con cuatro (4) miembros, Tiempo “Calendario” tiene cuatro (4) miembros también (considerando explicitamente Trimestres), y los Clientes (Paises) cuenta con seis (6) miembros. Por lo tanto, el número de celdas es igual a 4 * 4 * 6 = 96 celdas.

Supongamos que deseamos recuperar los datos que muestra el área sombreada en el cubo. El valor de la cantidad de ventas  en esta celda es de 966. Esta celda se encuentra en la intersección de Producto = Montañera, Tiempo = Trimestre 2, y el Cliente (Países) = Australia.

Para obtener estos datos según este ejemplo, la consulta MDX debe identificar de forma única la Celda que contiene el valor 966.

SELECT Measures.[Internet Sales Amount] ON COLUMNS

FROM [Adventure Works]

WHERE ( [Date].[Calendar].[Calendar Quarter].&[2011]&[2], [Product].[Product Line].[Mountain], [Customer].[Country].[Australia] )

Como se puede apreciar en la anterior consulta, se seleccionan el valor de las medidas Measures.[Internet Sales Amount] del cubo de la base de datos ‘Adventure Works’ basado en una condición particular que figure en la consulta de la clausula WHERE, la cual identifica unicamente la celda a tratar.

TUPLAS

Una expresión MDX que identifica unicamente a una celda o una sección de un cubo se denomina «Tupla».

Una tupla es representado por un Miembro de cada Dimensión, separados por una coma y encerrados entre paréntesis. A su vez, no necesariamente tiene que contener explícitamente los miembros de todas las dimensiones, cosa importante de comprender.

A continuación, les presento algunos ejemplos de tuplas basadas en la base de datos OLAP Adventure Works:

  • ([Cliente].[Pais].[Australia])
  • ([Tiempo].[Calendario].[2013].[H1 CY 2013].[Q1 CY 2013], [Cliente].[Pais].[Australia])
  • ([Tiempo].[Calendario].[2013].[H1 CY 2013].[Q1 CY 2013], [Producto].[Linea de Producto].[Montañera], [Cliente].[Pais].[Australia])

Como pueden apreciar en las anteriores tuplas, la 1 y la 2, no contienen miembros de todas las dimensiones del cubo. Sin embargo, ellas representan secciones del cubo.

Ahora, una sección del cubo representada por una tupla, se le denomina «Slice», lo cual no es otra cosa, que un subconjunto de ‘N’ matriz multidimensional que corresponde a un valor único para uno o más miembros de las dimensiones y no en el subconjunto como tal.

Una Tupla representada por un solo Miembro se llama “Tupla Simple” y no necesita ser encerrado entre paréntesis. Por ejemplo,

  • ([Cliente].[Pais].[Australia])

es una tupla simple y puede ser referido como

  • [Cliente].[PaIs].[Australia]

o simplemente

  • Cliente.Pais.Australia,

lo ven.

Ahora, cuando hay más de una dimensión en una tupla, estas sin embargo, deben ser encerrados entre paréntesis. Por tanto, cuando se hace referencia a la tupla

  • ([Cliente].[Pais].[Australia]),

realmente se refiere a la celda número 16 que corresponde al país de Australia según Gráfico No. 2 mostrado anteriormente. Por lo tanto, cuando se recuperan los datos bajo dominio por así decirlo de las celdas a las que apuntan esta tupla, se esta recuperando la cantidad de ventas de Internet ([Internet Sales Amount]) de todos los clientes en Australia según nuestro ejemplo, lo ven. El valor para la tupla [Cliente].[Pais].[Australia] es un agregado de las celdas englobadas en la cara frontal del cubo.

La consulta MDX para recuperar los datos representados por este tupla es:

SELECT Measures.[Internet Sales Amount] ON COLUMNS
FROM [Adventure Works]
WHERE ([Customer].[Country].[Australia])

Dando como resultado para esta consulta MDX según nuestro ejemplo: $9,061,000.58.

Importante comprender que no importa el orden de los miembros que se utilizan para representar una tupla, puesto que una tupla identifica una celda, no pudiendo contener a más de un miembro de cada dimensión según nuestro caso de ejemplo.

CONJUNTOS DE DATOS (SETS)

Un conjunto de Tuplas forma un nuevo objeto llamado un Conjunto de datos (Sets). Esta colección de tuplas se define utilizando exactamente el mismo conjunto de las dimensiones, tanto en el tipo y número. A su vez, estos Conjuntos de datos (Sets) se utilizan con frecuencia en las consultas y expresiones MDX.

Importante que comprendamos lo siguiente: Un conjunto de datos se especifica explicitamente bajo caracteres de llave ({ NombreObjeto }). Los Miembros de los Conjuntos de datos se separan por comas.

Los siguientes ejemplos ilustran conjuntos gratamente los conjuntos de datos:

  • Ejemplo 1: Las Tuplas (Clientes.Pais.Australia) y (Clientes.Pais.Canada) se resuelven exactamente en la misma jerarquía Clientes.País. Una colección de estas dos (2) tuplas es un conjunto válido y se especifica como: {(Clientes.Pais.Australia), (Clientes.Pais.Canada)}, lo ven. Ahora otro ejemplo.
  • Ejemplo 2: Cada una de las siguientes tuplas tienen tres (3) dimensiones: Tiempo, Productos y Clientes:

1.- ([Tiempo].[Calendario].[2012].[H1 CY 2012].[Q1 CY 20012, [Productos].[Linea de Producto].[Montañera], [Clientes].[Pais].[Australia]),
2.- ([Productos].[Linea de Producto].[Montañera], [Clientes].[Pais].[Australia], ([Tiempo].[Calendario].[2012].[H1 CY 2012].[Q1 CY 2012])
3.- ([Clientes].[Pais].[Australia], [Tiempo].[Calendario].[2012].[H1 CY 2012].[Q1 CY 2012], [Productos].[Linea de Producto].[Montañera])

Los miembros de la jerarquía [Tiempo].[Calendario] de los tres (3) tuplas anteriores son diferentes; por lo tanto, estas tuplas se refieren a diferentes celdas.

Teniendo en cuenta que de acuerdo con la definición de lo que es un conjunto, una colección de estas tuplas es un conjunto válido y se muestra aquí:

{ ([Tiempo].[Calendario].[2012].[H1 CY 2012].[Q1 CY 2012], [Productos].[Linea de Productos].[Montañera], [Clientes].[Pais].[Australia]), ([Productos].[Linea de Productos].[Montañera], [Clientes].[Pais].[Australia],
([Tiempo].[Calendario].[2010].[H1 CY 2010].[Q1 CY
2010]),([Clientes].[Pais].[Australia], [Tiempo].[Calendario].[2011].[H1 CY
2011].[Q1 CY 2011], [Productos].[Linea de Productos].[Montañera] )}

Por tanto, habiendo expuesto lo anterior, se entendera que un conjunto puede contener cero, uno, o más tuplas, cierto. Un conjunto con cero tuplas se conoce como un conjunto vacío. Un conjunto vacío se representa de la siguiente forma:

{ }

Un conjunto puede contener tuplas duplicadas. Un ejemplo de un conjunto con tales caracteristicas es:

{Clientes.Pais.Australia, Clientes.Pais.Canada, Clientes.Pais.Australia}

Como pueden observar, este grupo contiene dos (2) instancias de la tupla Clientes.Pais.Australia.

Para terminar el presente artículo, considero que debemos tener en cuenta algunos puntos importantes a la hora de entender el tema acerca de tuplas y conjuntos:

  1. Un miembro de una dimensión (Por ejemplo: ([Tiempo].[Calendario].[2011].[H1 CY 2011].[Q1 CY 2011]) de por sí mismo forma una tupla y un conjunto. Por lo tanto, se puede utilizar como tal en consultas MDX.
  2. Si hay una tupla especificada por una sola jerarquía, no necesitaremos los paréntesis para especificarlo como un conjunto. Esta tupla puede ser utilizado directamente en las consultas MDX, lo ven.
  3. Cuando hay una única tupla especificada en una consulta, nosotros no necesitaremos llaves para indicar que se debe tratar como un conjunto. Ya que cuando se ejecuta dicha consulta, la tupla se convierte implícitamente en un conjunto.

En general, es una buena práctica el usar el paréntesis y las llaves mientras escribimos consultas MDX, ya que con esto nos aseguramos que las tuplas y los conjuntos especificados en nuestras consultas MDX están exactas.

Hasta aquí el presente temario referente al Lenguaje de Programación Analítico MDX.

Espero que les aproveche en la compresión básica del mismo.

Nos pillamos en una próxima, Winking smile.

Serie “Análisis de datos”: Conceptos Generales de MDX (Parte 1).


Continuando con la serie “Análisis de datos”, en esta entrega les comentare brevemente sobre diversos tópicos referentes a los conceptos básicos del lenguaje MDX.

CONCEPTO GENERAL

Primero que todo debemos tener en cuenta que una base de datos multidimensional en MS SQL Server Analysis Services puede contener uno o varios cubos en su interior.

Un cubo es un objeto que es diseñado y usado por usuarios que analisan datos. Cada cubo puede contener al menos dos Dimensiones (una de las cuales es una dimensión llamada Medidas), pero típicamente contendran mas de dos dimensiones.

En el siguiente gráfico, podemos apreciar el contenido de la estructura de un cubo en la base de datos de ejemplo Adventure Works.

A su vez, ustedes pueden descargar e instalar esta base de datos de ejemplo y sus juguetes decorativos en el siguiente enlace: Adventure Works for SQL Server 2012.

MEDIDAS Y GRUPOS DE MEDIDAS

El objeto “Medidas” dentro de un cubo, es una dimensión de cubo especial que representan un conjunto de medidas. Estas son entidades cualitativas que se utilizan para el análisis.

Cada Medida es parte de una entidad llamada “Grupo de Medida”. Los Grupos de Medidas son colecciones de medidas relacionadas, y cada Medida solo puede ser parte de un único grupo de medida. Los grupos de medidas son principalmente utilizados para fines de navegación, así facilitando su lectura desde las herramientas clientes.

Los grupos de medidas, no se utilizan en las consultas MDX al consultar medidas. Sin embargo, se pueden utilizar en ciertas funciones MDX.

JERARQUÍAS Y NIVELES DE JERARQUÍAS

En el ejemplo de Adventure Works, se puede apreciar que las dimensiones tienen una o mas jerarquías, y cada jerarquía contiene uno o mas niveles.

El gráfico descriptivo que se muestra a continuación, muestra una simplificación de un cubo con tres (3) jerarquías:

  • Calendario (Calendar)
  • Linea de Productos (Product Line)
  • Paises (Country)

Como podemos apreciar, la jerarquía Calendario de la dimensión Tiempo consta de cinco (5) niveles:

  • Año
  • Semestre
  • Trimestre
  • Mes
  • Día

mientras que las jerarquías Linea de Productos y Paises son jerarquías de atributos con solo dos niveles:

  • Todos (All)

y según el escenario

  • Linea de Producto
  • Paises

respectivamente.

MIEMBROS

Cada Jerarquía contiene uno o más elementos que se conocen como “Miembros”, y cada miembro corresponde a una o más ocurrencias del valor de referencia en la tabla de dimensiones subyacente.

En el gráfico a continuación, les muestros los miembros de las jerarquías en modo de desarrollo de las dimensiones Clientes, Empleados y Organización de la base de datos de ejemplo Adventure Works.

Pueden obeservar que para la dimensión “Clientes”, se encuentra la jerarquía homónima, habitando en la misma los ítems Ciudad (City), Paises (Country) los cules forman parte (miembros) de la jerarquía Geografia. La de “Empleados” de igual forma que la anterior pero identificamos los ítems Departamento (Departament Name) y Genero (Gender), miembros de esta jerarquía en esta dimensión. Y la dimensión Organización, que no posee según el ejemplo Jerarquías pero si contiene miembros que según su contexto, imparte información de análisis de acuerdo a los requerimientos de negocio que se le plantee, consultandose en cualquier lugar del cubo en este caso.

En MDX, cada Miembro especifico de una Jerarquía, es identificado por un nombre único. A su vez, se puede acceder a un miembro de una dimensión con su nombre, el de la jerarquía y el nombre del nivel (ítems) o la ruta de la clave (key) como por ejemplo el miembro [T1 CY 2013] dela jerarquía Calendario representado de la siguiente manera:

  • [Tiempo].[Calendario].[Trimestre].[T1 CY 2013]

Hay que tener en cuenta, que se debe utilizar los corchetes cada vez que tenga un nombre que contiene un espacio, un número o palabra reservada MDX. De lo contrario, se podra omitir dichos corchetes. En la expresión anterior, el nombre de la dimensión Tiempo (Date en inglés) es una palabra reservada MDX, por lo cual DEBE estar encerrada entre corchetes.

Segurencia: Aunque los corchetes son opcionales, es una buena práctica utilizarlos.

Los tres (3) ejemplos siguientes, son validos para el miembro [T1 CY 2013]:

  • [Tiempo].[Calendario].[T1 CY 2013]
  • [Tiempo].[Calendario].[CY 2013].[H1 CY 2013].[T1 CY 2013]
  • [Tiempo].[Calendario].[Trimestre].&[2013]&[1]

En la primera, el miembro esta representado por el siguiente formato: [Dimension].[Jerarquia].[Miembro]. La idea de esta acción al escribirlo de esta forma, es buscar que hayan conflicto cuando dos de sus miembros posean igual nombre. Lo anterior se traduciria coloquialmente de la siguiente forma: Si el Trimestre 1 de cada año se denomina T1, no se podria utilizar este formato, que se necesita para calificar con el nombre del nivel en la expresión MDX. Utilizando este formato, siempre se recuperara T1 para el primer año de la jerarquía, lo ven.

En el segundo formato, se puede observar la ruta de navegación para el miembro que vera a su vez, todos los demás miembros en dicha ruta subsecuentamente.

El formato final que utiliza la ruta clave, por así decirlo, en el que las claves de los miembros se representando como [Miembros], estando estos mismos precedido por el signo ampersand (&) utilizando el siguiente esquema para acceder a un miembro:

Cabe destacar que esta es la forma como particularmente yo lo utilizo. Los otros formatos que he enunciado en el presente post, se les denomina “Nombre unico” (UniqueName en inglés) de un miembro de la dimensión especifica y se incluye unicamente solo como referencia.

Una recomendación que les imparto al respecto es que puedes recuperar y utilizar el nombre único, que el mismo motor genera cuando es consultado un miembro especifico, vale.

Hasta aquí les expongo el presente post, en la próxima entrega le culminare los tópicos faltantes que son

  • Celdas (Cells)
  • Tuplas (Tuples)
  • Conjuntos de Datos (Sets)

Nos pillamos en la próxima entrega, Smile.

Serie “Análisis de datos”: Entendiendo MDX.


En la presente serie, iniciare unos breves y practicos comentarios sobre el mundo analitico de datos y sus juguetes. Ante tantas consultas que me formulan al referente, decidi iniciarla por uno de los protagonistas del mismo y es su lenguaje base: MDXMutliDimensional eXpressions.

¿QUÉ ES MDX?

Así como lenguaje de consulta estructurado que maneja MS SQL Server 2012 (T-SQL) es un lenguaje de consulta que se utiliza para recuperar datos de bases de datos relacionales, las expresiones multidimensionales (MDX) es un lenguaje de consulta que se utiliza para recuperar datos de bases de datos hospedadas en SQL Server Analisis Services.

MDX admite y soporta dos escenarios y modos de trabajo distintos los cuales serian:

  • Lenguaje de expresiones: Define y manipula objetos de Analysis Services, así como datos para calcular valores almacenados en estructuras OLAP.
  • Lenguaje de consulta: Nos permite recuperar datos desde Analysis Services.

HISTORIA

MDX fue originalmente diseñado por Microsoft e introducido en 1998 con SQL Server Analysis Services 7.0, mas no obstante, este es un lenguaje de consulta estandar, basado para recuperar datos de bases de datos OLAP exclusivamente.

Como estandar de la industria del ramo, muchos otros proveedores “OLAP” soportan MDX como por ejemplo:

En la actualidad, hay quienes quieren ampliar el estándar para adicionarles mas funcionalidadesl, así como extensiones MDX al lenguaje; y de hecho, hay varias que han sido desarrolladas por compañías de terceros, pero las partes constitutivas de cualquier extensión deben ser compatibles con el estándar base de MDX provisto por Microsoft.

Cabe destacar también que Analysis Services proporciona otras extensiones definidas con el estándar MDX para OLE DB para OLAP.

Hasta aquí le entrego esta intro al tema. El próximo post les hablare un poco sobre los conceptos centrales de MDX que abracan:

  • Medidas y Grupo de Medidas
  • Jerarquías y Niveles de Jerarquías
  • Miembros
  • Celdas
  • Tuplas
  • Conuntos de datos (“Sets”) entre otros…

Nos pillamos proximamente, Winking smile.

Webcast de MS SQL Server 2012 a través de SQL PASS Venezuela, segundo semestre 2013


 

Hola a tod@s mis lectores y seguidores.

Les extiendo amablemente la invitación a la serie y programación de webcasts con temas ampliamente tecnologicos de muchos ámbitos (Desarrollo, Administración, BI y Azure), referentes a MS SQL Server 2012, y especificamente en versión SP1.

En el siguiente enlace podrás inscribirte gratuitamente: http://bit.ly/SQLPASSVENEZUELA.

A continuación, les listo el temario con el título de la conferencia, su descripción, el nombre del expositor(a), la fecha y hora:

Título: Fundamentos de diseños de bases de datos
Descripción: Establecer y afianzar los fundamentos básicos en el diseño de bases de datos en las empresas del día de hoy.
Speaker: José Redondo
Fecha: Jueves, 20 de Junio de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Fundamentos en la aplicación de una Plataforma BI
Descripción: Concretar y definir los aspectos fundamentales en la generación de proyectos de Inteligencia de Negocio en las empresas del día de hoy.
Speaker: Jesús Gil
Fecha: Viernes, 28 de Junio de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Optimización de aplicaciones de bases de datos OLTP
Descripción: Robustecer y consolidar el rendimiento en las aplicaciones de bases de datos transaccionales en escenarios con alto volúmenes de transacciones diarias en las empresas de
Speaker: Edinson Medina
Fecha: Martes, 09 de Julio de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Escribiendo código T-SQL eficientemente
Descripción: Afianzar y renovar conceptos claves en la escritura de código T-SQL en nuestros escenarios de datos del día de hoy.
Speaker: José Redondo
Fecha: Jueves, 18 de Julio de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Optimizando consultas utilizando estadísticas
Descripción: Aprovechar la información aportada por las estadísticas de los índices de tablas de datos para buscar la mejor manera de brindar resultados eficientes en nuestros sistemas de bases de datos del día de hoy.
Speaker: Guillermo Taylor
Fecha: Martes, 30 de Julio de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Utilizando el Plan Cache para optimizar procesos de consultas
Descripción: Emplear todas las bondades del Plan Cache que nos brinda SQL Server para fortalecer las ejecuciones de las consultas en nuestros escenarios de datos.
Speaker: John Bulla
Fecha: Martes, 13 de Agosto de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Aplicando AlwaysOn Availability Groups en escenarios reales
Descripción: Suministrar y consolidar las nuestras bondades de Alta Disponibilidad ofrecida por SQL Server 2012 a las empresas de hoy.
Speaker: Edinson Medina
Fecha: Miercoles, 28 de Agosto de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Integration Services vs. T-SQL: Cargando un almacén de datos
Descripción: Fundamentar y adherir las decisiones más acorde en nuestros escenarios de datos empresariales referente a la población de las bodegas de datos a través de mecanismos apropiados en consonancia a las pericias adquiridas por nuestro equipo de trabajo empresarial en el día de hoy.
Speaker: José Redondo
Fecha: Jueves, 05 de Septiembre de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Buenas prácticas en el desarrollo de bases de datos multidimensionales con SSAS
Descripción: Disponer y validar las buenas prácticas en la ejecución de proyectos de desarrollos de aplicaciones OLAP en las empresas del día de hoy.
Speaker: Mary Arcia
Fecha: Martes, 24 de Septiembre de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Introducción a SSRS 2012
Descripción: Presentación del servicio de reportes empresariales ofrecido por SQL Server 2012 desde todos los ángulos a servir a las empresas del día de hoy.
Speaker: Juan Romagosa
Fecha: Jueves, 10 de Octubre de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Generar informes vistosos con SSRS 2012
Descripción: Establecer y diseñar estrategias novedosas en el diseño y desarrollo de informes empresariales con carácter y personalidad gerencial en las empresas de hoy.
Speaker: Mary Arcia
Fecha: Miercoles, 30 de Octubre de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Introducción a SQL Azure
Descripción: Presentación del servicio de almacenamiento de datos en la nube por parte de Microsoft a las empresas de hoy.
Speaker: Miguel Mendoza
Fecha: Martes, 12 de Noviembre de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Como migrar tus bases de datos SQL Server 2012 a SQL Azure
Descripción: Definir y validar los pasos a establecer en el proceso de migración de los sistemas de información transaccional en nuestras empresas a la nube.
Speaker: José Redondo / Jesús Gil
Fecha: Viernes, 29 de Noviembre de 2013
Hora: 12:30PM (Hora Venezuela)
Título: Diseño de aplicaciones de bases de datos SQL Azure
Descripción: Aplicar y establecer las normativas practicas a la hora de diseñar eficientes aplicaciones de bases de datos en la nube.
Speaker: José Redondo
Fecha: Jueves, 12 de Diciembre de 2013
Hora: 12:30PM (Hora Venezuela)

Espero les sea de mucho provecho los mismos. Animate e inscribete, a que esperas.

Tod@s están cordialmente invitados.

Nos pillamos en próxima, Winking smile.

Pie