diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION1/EJERCICIO1/ejercicio1.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION1/EJERCICIO1/ejercicio1.py new file mode 100644 index 000000000..4a8f16903 --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION1/EJERCICIO1/ejercicio1.py @@ -0,0 +1 @@ +print('Hola Mundo') \ No newline at end of file diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION1/EJERCICIO2/ejercicio2.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION1/EJERCICIO2/ejercicio2.py new file mode 100644 index 000000000..adb8f00de --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION1/EJERCICIO2/ejercicio2.py @@ -0,0 +1,2 @@ +nombre : str = ('Alex') +print(f"Hola {nombre}") \ No newline at end of file diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION2/EJERCICIO1/ejercicio1.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION2/EJERCICIO1/ejercicio1.py new file mode 100644 index 000000000..816ec0473 --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION2/EJERCICIO1/ejercicio1.py @@ -0,0 +1,20 @@ + +def calcular_inversion(inversion, interes, años): + inversion_final = inversion * (1 + interes/100) ** años + return inversion_final + + +def main(): + try: + inversion = float(input("¿Cuánto quieres invertir?: ")) + interes = float(input("¿Cuál es el interés anual?: ")) + años = int(input("¿Cuántos años vas a mantener la inversión?: ")) + inversion_generada = calcular_inversion(inversion, interes, años) + interes_generado = inversion_generada - inversion + print(f"En {años} años habrás recibido {interes_generado:.2f}€ de interés") + + except ValueError: + print("Error: Introduce un número válido") + +if __name__ == "__main__": + main() diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION3/EJERCICIO1/ejercicio1.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION3/EJERCICIO1/ejercicio1.py new file mode 100644 index 000000000..a92784d9a --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION3/EJERCICIO1/ejercicio1.py @@ -0,0 +1,46 @@ +def calcular_inversion(inversion, interes, años): + inversion_final = inversion * (1 + interes / 100) ** años + return inversion_final + +def main(): + while True: + try: + print("Hola. Bienvenido al sistema de cálculo de inversiones. ¿Qué quieres hacer?") + print("[1] Calcular una inversión") + print("[X] Salir") + opcion = input("Elige una opción: ").strip().upper() + + if opcion == '1': + while True: + try: + inversion = float(input("¿Cuánto quieres invertir?: ")) + interes = float(input("¿Cuál es el interés anual?: ")) + años = int(input("¿Cuántos años vas a mantener la inversión?: ")) + + inversion_final = calcular_inversion(inversion, interes, años) + interes_ganado = inversion_final - inversion + + print(f"En {años} años habrás recibido {interes_ganado:.2f}€ de interés.") + print("¿Qué quieres hacer ahora?") + print("[1] Calcular una nueva inversión") + print("[X] Salir") + opcion = input("Elige una opción: ").strip().upper() + + if opcion == 'X': + print("¡Nos vemos!") + exit() + elif opcion != '1': + print("Opción no válida. Por favor, elige una opción válida.") + except ValueError: + print("Error: Introduce un número válido") + elif opcion == 'X': + print("¡Nos vemos!") + exit() + else: + print("Opción no válida. Por favor, elige una opción válida.") + + except ValueError: + print("Error: Introduce un número válido") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO1/ejercicio1.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO1/ejercicio1.py new file mode 100644 index 000000000..b44a300cf --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO1/ejercicio1.py @@ -0,0 +1,14 @@ +def es_primo(numero): + if numero <= 1: + return False + for i in range(2, int(numero ** 0.5) + 1): + if numero % i == 0: + return False + return True + +def mostrar_primos(inicio, fin): + for numero in range(inicio, fin + 1): + if es_primo(numero): + print(numero) + +mostrar_primos(10, 50) \ No newline at end of file diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO1/ejercicio2.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO1/ejercicio2.py new file mode 100644 index 000000000..03c351f2a --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO1/ejercicio2.py @@ -0,0 +1,14 @@ +def es_primo(numero): + if numero <= 1: + return False + for i in range(2, int(numero ** 0.5) + 1): + if numero % i == 0: + return False + return True + +numero = 29 +if es_primo(numero): + print(f"El número {numero} es primo.") +else: + print(f"El número {numero} no es primo.") + diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO1/ejercicio3.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO1/ejercicio3.py new file mode 100644 index 000000000..32bd62e68 --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO1/ejercicio3.py @@ -0,0 +1,10 @@ +def es_bisiesto(año): + if (año % 4 == 0 and año % 100 != 0) or (año % 400 == 0): + return True + return False + +año = 2024 +if es_bisiesto(año): + print(f"El año {año} es bisiesto.") +else: + print(f"El año {año} no es bisiesto.") \ No newline at end of file diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO2/ejercicio2.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO2/ejercicio2.py new file mode 100644 index 000000000..92437b670 --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO2/ejercicio2.py @@ -0,0 +1,9 @@ + +import requests +import pandas + +def main(): + print("¡Hola, Mundo!") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO2/requirements.txt b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO2/requirements.txt new file mode 100644 index 000000000..65a42bead --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO2/requirements.txt @@ -0,0 +1,2 @@ +requests +pandas diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO3/ejercicio3.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO3/ejercicio3.py new file mode 100644 index 000000000..07549b741 --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION4/EJERCICIO3/ejercicio3.py @@ -0,0 +1,17 @@ +import requests + +def obtener_usuario_aleatorio(): + url = "https://randomuser.me/api" + response = requests.get(url) + + if response.status_code == 200: + data = response.json() + usuario = data['results'][0] + nombre = usuario['name']['first'] + apellidos = usuario['name']['last'] + print(f"Nombre: {nombre}, Apellidos: {apellidos}") + else: + print("Error al realizar la petición") + +if __name__ == "__main__": + obtener_usuario_aleatorio() \ No newline at end of file diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO1/ejercicio1.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO1/ejercicio1.py new file mode 100644 index 000000000..cfd54699a --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO1/ejercicio1.py @@ -0,0 +1,140 @@ +import pandas as pd + +# Leer el archivo CSV +df = pd.read_csv('pokemon_data.csv') + +# IMPRIMIR TODOS LOS VALORES +print("TODOS LOS VALORES:") +print(df) + +# IMPRIMIR LOS PRIMEROS 5 +print("\nPRIMEROS 5:") +print(df.head()) + +# IMPRIMIR LOS ÚLTIMOS 5 +print("\nÚLTIMOS 5:") +print(df.tail()) + +# OBTENER NOMBRES DE LAS COLUMNAS +print("\nNOMBRES DE LAS COLUMNAS:") +print(df.columns) + +# OBTENER TODOS LOS NOMBRES +print("\nTODOS LOS NOMBRES:") +print(df['Name']) + +# OBTENER TODOS LOS NOMBRES Y VELOCIDADES +print("\nTODOS LOS NOMBRES Y VELOCIDADES:") +print(df[['Name', 'Speed']]) + +# LOS PRIMEROS 5 NOMBRES USANDO [::] +print("\nPRIMEROS 5 NOMBRES USANDO [::]:") +print(df['Name'][:5]) + +# OBTENER TODAS LAS FILAS +print("\nTODAS LAS FILAS:") +print(df.iloc[:]) + +# OBTENER UN RANGO DE FILAS +print("\nRANGO DE FILAS (5-10):") +print(df.iloc[5:10]) + +# OBTENER EL NOMBRE DE LA FILA 10 +print("\nNOMBRE DE LA FILA 10:") +print(df.iloc[9]['Name']) + +# ITERAR POR TODOS Y MOSTRAR EL ÍNDICE Y NOMBRE DE CADA FILA +print("\nÍNDICE Y NOMBRE DE CADA FILA:") +for index, row in df.iterrows(): + print(index, row['Name']) + +# POKEMONS DE TIPO 1 == WATER +print("\nPOKEMONS DE TIPO 1 == WATER:") +print(df[df['Type 1'] == 'Water']) + +# ESTADÍSTICAS (usando Describe del DataFrame) +print("\nESTADÍSTICAS:") +print(df.describe()) + +# ORDENACIÓN POR NOMBRE ASCENDENTE +print("\nORDENACIÓN POR NOMBRE ASCENDENTE:") +print(df.sort_values('Name')) + +# CREAR UNA COLUMNA EXTRA CALCULADA +df['Total'] = df['HP'] + df['Attack'] + df['Defense'] + df['Speed'] +print("\nCON COLUMNA TOTAL:") +print(df) + +# ELIMINAR LA COLUMNA TOTAL +df = df.drop(columns=['Total']) +print("\nSIN COLUMNA TOTAL:") +print(df) + +# FILTRAR POKEMONS DE TIPOS "GRASS" Y "POISON" +print("\nPOKEMONS DE TIPOS 'GRASS' Y 'POISON':") +print(df[(df['Type 1'] == 'Grass') & (df['Type 2'] == 'Poison')]) + +# FILTRAR POKEMONS DE TIPO "FIRE" Ó "POISON" +print("\nPOKEMONS DE TIPO 'FIRE' Ó 'POISON':") +print(df[(df['Type 1'] == 'Fire') | (df['Type 2'] == 'Poison')]) + +# FILTRAR POKEMONS DE TIPO "GRASS" Y "POISON" Y UN HP >= 70 +print("\nPOKEMONS DE TIPO 'GRASS' Y 'POISON' Y UN HP >= 70:") +print(df[(df['Type 1'] == 'Grass') & (df['Type 2'] == 'Poison') & (df['HP'] >= 70)]) + +# FILTRAR POKEMONS CON NOMBRE "MEGA" +print("\nPOKEMONS CON NOMBRE 'MEGA':") +print(df[df['Name'].str.contains('Mega')]) + +# FILTRAR POKEMONS SIN NOMBRE "MEGA" +print("\nPOKEMONS SIN NOMBRE 'MEGA':") +print(df[~df['Name'].str.contains('Mega')]) + +# FILTRAR POKEMONS CUYOS NOMBRES COMIENCEN CON "PI" +print("\nPOKEMONS CUYOS NOMBRES COMIENCEN CON 'PI':") +print(df[df['Name'].str.startswith('Pi')]) + +# RENOMBRADO DE COLUMNA "FIRE" a "FLAME" +df.rename(columns={'Type 1': 'Flame'}, inplace=True) +print("\nRENOMBRADO DE 'Type 1' A 'Flame':") +print(df) + +# RENOMBRAR DE NUEVO A "FIRE" LA COLUMNA "FLAME" RECIÉN CAMBIADA +df.rename(columns={'Flame': 'Type 1'}, inplace=True) +print("\nRENOMBRADO DE 'Flame' A 'Type 1':") +print(df) + +# CAMBIAR A TODOS LOS POKEMON LEGENDARIOS A TIPO "FIRE" +df.loc[df['Legendary'] == True, 'Type 1'] = 'Fire' +print("\nCAMBIAR A TODOS LOS POKEMON LEGENDARIOS A TIPO 'FIRE':") +print(df) + +# (Agrupación - groupBy) ESTADÍSTICAS DE MEDIA POR TIPO DE POKEMON y ORDENADOS POR DEFENSA +print("\nESTADÍSTICAS DE MEDIA POR TIPO DE POKEMON ORDENADOS POR DEFENSA:") +print(df.groupby('Type 1').mean(numeric_only=True).sort_values('Defense')) + +# (Agrupación - groupBy) ESTADÍSTICAS DE MEDIA POR TIPO DE POKEMON y ORDENADOS POR ATAQUE +print("\nESTADÍSTICAS DE MEDIA POR TIPO DE POKEMON ORDENADOS POR ATAQUE:") +print(df.groupby('Type 1').mean(numeric_only=True).sort_values('Attack')) + +# (Agrupación - groupBy) ESTADÍSTICAS DE MEDIA POR TIPO DE POKEMON y ORDENADOS POR HP +print("\nESTADÍSTICAS DE MEDIA POR TIPO DE POKEMON ORDENADOS POR HP:") +print(df.groupby('Type 1').mean(numeric_only=True).sort_values('HP')) + +# (Agrupación - groupBy) ESTADÍSTICAS DE SUMA POR TIPO DE POKEMON +print("\nESTADÍSTICAS DE SUMA POR TIPO DE POKEMON:") +print(df.groupby('Type 1').sum(numeric_only=True)) + +# (Agrupación - groupBy) ESTADÍSTICAS DE NÚMERO DE POKEMONS POR TIPO 1 DE POKEMON +print("\nESTADÍSTICAS DE NÚMERO DE POKEMONS POR TIPO 1 DE POKEMON:") +print(df.groupby('Type 1').count()) + +# (Agrupación - groupBy) ESTADÍSTICAS DE NÚMERO DE POKEMONS POR TIPO 1 y 2 DE POKEMON +print("\nESTADÍSTICAS DE NÚMERO DE POKEMONS POR TIPO 1 y 2 DE POKEMON:") +print(df.groupby(['Type 1', 'Type 2']).count()) + +# LEE EL ARCHIVO CVS SEPARÁNDOLO POR CHUNKS Y CON UN TAMAÑO DE (chunksize=5) +print("\nLEER EL ARCHIVO CSV POR CHUNKS (chunksize=5):") +chunk_size = 5 +for chunk in pd.read_csv('pokemon_data.csv', chunksize=chunk_size): + print(chunk) \ No newline at end of file diff --git a/PROFESORES/COMUN/PYTHON/Datos/pokemon_data.csv b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO1/pokemon_data.csv similarity index 100% rename from PROFESORES/COMUN/PYTHON/Datos/pokemon_data.csv rename to ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO1/pokemon_data.csv diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO2/ejercicio2.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO2/ejercicio2.py new file mode 100644 index 000000000..bc76dfbae --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO2/ejercicio2.py @@ -0,0 +1,45 @@ +class Automovil: + def __init__(self, marca, modelo, año): + self.marca = marca + self.modelo = modelo + self.año = año + self.encendido = False + self.velocidad = 0 + + def arrancar(self): + if not self.encendido: + self.encendido = True + print(f"El automóvil {self.marca} {self.modelo} ha arrancado.") + else: + print(f"El automóvil {self.marca} {self.modelo} ya está encendido.") + + def acelerar(self, incremento): + if self.encendido: + self.velocidad += incremento + print(f"El automóvil {self.marca} {self.modelo} ha acelerado a {self.velocidad} km/h.") + else: + print(f"El automóvil {self.marca} {self.modelo} está apagado. No se puede acelerar.") + + def frenar(self, decremento): + if self.encendido and self.velocidad > 0: + self.velocidad -= decremento + if self.velocidad < 0: + self.velocidad = 0 + print(f"El automóvil {self.marca} {self.modelo} ha frenado a {self.velocidad} km/h.") + else: + print(f"El automóvil {self.marca} {self.modelo} está apagado o ya está detenido.") + + def parar(self): + if self.encendido: + self.encendido = False + self.velocidad = 0 + print(f"El automóvil {self.marca} {self.modelo} se ha detenido.") + else: + print(f"El automóvil {self.marca} {self.modelo} ya está apagado.") + + +auto = Automovil("Toyota", "Corolla", 2020) +auto.arrancar() +auto.acelerar(50) +auto.frenar(20) +auto.parar() \ No newline at end of file diff --git a/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO3/ejercicio3.py b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO3/ejercicio3.py new file mode 100644 index 000000000..a39615961 --- /dev/null +++ b/ALUMNOS/MDAA/ALEX_REVERT/PYTHON/SESION5/EJERCICIO3/ejercicio3.py @@ -0,0 +1,91 @@ +class Automovil: + def __init__(self, marca, modelo, año): + self.marca = marca + self.modelo = modelo + self.año = año + self.encendido = False + self.velocidad = 0 + + def arrancar(self): + if not self.encendido: + self.encendido = True + print(f"{self.articulo()} {self.marca} {self.modelo} ha arrancado.") + else: + print(f"{self.articulo()} {self.marca} {self.modelo} ya está encendido.") + + def acelerar(self, incremento): + if self.encendido: + self.velocidad += incremento + print(f"{self.articulo()} {self.marca} {self.modelo} ha acelerado a {self.velocidad} km/h.") + else: + print(f"{self.articulo()} {self.marca} {self.modelo} está apagado. No se puede acelerar.") + + def frenar(self, decremento): + if self.encendido and self.velocidad > 0: + self.velocidad -= decremento + if self.velocidad < 0: + self.velocidad = 0 + print(f"{self.articulo()} {self.marca} {self.modelo} ha frenado a {self.velocidad} km/h.") + else: + print(f"{self.articulo()} {self.marca} {self.modelo} está apagado o ya está detenido.") + + def parar(self): + if self.encendido: + self.encendido = False + self.velocidad = 0 + print(f"{self.articulo()} {self.marca} {self.modelo} se ha detenido.") + else: + print(f"{self.articulo()} {self.marca} {self.modelo} ya está apagado.") + + def articulo(self): + return "El automóvil" + +class Coche(Automovil): + def acelerar(self, incremento=10): + super().acelerar(incremento) + + def frenar(self, decremento=10): + super().frenar(decremento) + + def articulo(self): + return "El coche" + +class Moto(Automovil): + def acelerar(self, incremento=15): + super().acelerar(incremento) + + def frenar(self, decremento=15): + super().frenar(decremento) + + def articulo(self): + return "La moto" + +class Camion(Automovil): + def acelerar(self, incremento=5): + super().acelerar(incremento) + + def frenar(self, decremento=5): + super().frenar(decremento) + + def articulo(self): + return "El camión" + +# Ejemplo de uso +coche = Coche("Toyota", "Corolla", 2020) +moto = Moto("Yamaha", "MT-07", 2021) +camion = Camion("Volvo", "FH16", 2019) + +coche.arrancar() +coche.acelerar() +coche.frenar() +coche.parar() + +moto.arrancar() +moto.acelerar() +moto.frenar() +moto.parar() + +camion.arrancar() +camion.acelerar() +camion.frenar() +camion.parar() \ No newline at end of file diff --git a/ALUMNOS/MDAA/JOAN_GILABERT/SQL/NOTAS_SQL.txt b/ALUMNOS/MDAA/JOAN_GILABERT/SQL/NOTAS_SQL.txt new file mode 100644 index 000000000..e9fd711c4 --- /dev/null +++ b/ALUMNOS/MDAA/JOAN_GILABERT/SQL/NOTAS_SQL.txt @@ -0,0 +1,89 @@ +CREATE TABLE IF NOT EXISTS reviews_jg( + film_id integer NOT NULL, + customer_id integer NOT NULL, + review_date timestamp NOT NULL DEFAULT now(), + review_description varchar(50), + CONSTRAINT reviews_film_pkey PRIMARY KEY (film_id, customer_id) +); + +--Añadir estrellas a la review +alter table reviews_jg +add column review_stars int; + +--Renombrar la columna +alter table reviews_jg +rename column review_description to review_opinion; + +--Cambiar tipo de dato +alter table reviews_jg +alter column review_stars type varchar; + +create or replace VIEW joan_gilabert AS + SELECT a.actor_id, a.first_name, a.last_name, a.last_update, f.title, count(f.film_id) + FROM film_actor fa +LEFT JOIN actor a on fa.actor_id=a.actor_id +LEFT JOIN film f on fa.film_id=f.film_id +group by a.actor_id ; + + + +create or replace VIEW top5 AS + SELECT + concat(first_name,' ' , last_name) as nombre_completo, + sum(p.amount) as suma, + round(avg(return_date::date - rental_date::date),2) as media_tiempo, + count(i.film_id) as número_películas + FROM payment p +LEFT JOIN customer c on p.customer_id=c.customer_id +LEFT JOIN rental r on r.rental_id=p.rental_id +left join inventory i on i.inventory_id=r.inventory_id +group by 1 +order by sum(p.amount) DESC +limit 5; + +create or replace VIEW down5 AS + SELECT concat(first_name,' ' , last_name) as nombre_completo, + sum(p.amount) as suma, + round(avg(return_date::date - rental_date::date),2) as media_tiempo, + count(i.film_id) as número_películas + FROM payment p +LEFT JOIN customer c on p.customer_id=c.customer_id +LEFT JOIN rental r on r.rental_id=p.rental_id +left join inventory i on i.inventory_id=r.inventory_id +group by 1 +order by sum(p.amount) ASC +limit 5; + +create view kpis as +select avg(down5.suma), 'down5' as tipo from down5 +union all +select avg(top5.suma), 'top5' as tipo from top5; + + +SELECT sum(p.amount), count(rental_id), round(sum(p.amount)/count(rental_id),2) as ticket_media from payment p +where customer_id in ( + select customer_id from rental r where return_date::date - rental_date::date>3 +); + +with my_sub_query as + (SELECT customer_id, sum(amount) as total + FROM payment + group by customer_id +) + select * from my_sub_query where total>190 + +with sub as +(select a.address, + s.first_name, + sum(p.amount) as total, + count(p.customer_id) as clientes, + round(avg(return_date::date - rental_date::date),2) as media +from staff s +left join payment p on p.staff_id=s.staff_id +left join address a on a.address_id=s.address_id +left join rental r on r.rental_id=p.rental_id +group by 1,2 +order by total desc +limit 1 +) +select * from sub diff --git a/ALUMNOS/MDAA/JUAN_BESSINI/SQL/Bessini-SQL-Part1-ED1.txt b/ALUMNOS/MDAA/JUAN_BESSINI/SQL/Bessini-SQL-Part1-ED1.txt new file mode 100644 index 000000000..81df98f88 --- /dev/null +++ b/ALUMNOS/MDAA/JUAN_BESSINI/SQL/Bessini-SQL-Part1-ED1.txt @@ -0,0 +1,112 @@ +--¿Como se llaman los actoes que empiezan por la letra A? +SELECT * +FROM actor +WHERE first_name LIKE 'A%'; + +--¿Cuales son las peliculas que podemos alquilar por mas de 10€? + +SELECT title, rental_rate +FROM film +WHERE rental_rate > 10; + +--¿Cuantas peliculas podemos alquilar entre 5 y 10 euros? +SELECT COUNT(*) AS peliculas_entre_5_y_10 +FROM film +WHERE rental_rate BETWEEN 5 AND 10; + +--¿Cuantas peliculas podemos alquilar por menos de 5€ y con una duración menor a 100 min? +SELECT COUNT(*) AS peliculas_baratas_y_cortas +FROM film +WHERE rental_rate < 5 AND length < 100; + +--El responsanle de tienda está interesado en conocer mejor las peliculas... Desea obtener un listado de las películas por orden de duración (de menos duración a más duración) y quiere conocer los títulos de las 5 películas más cortas del videoclub. +SELECT title, length +FROM film +ORDER BY length ASC +LIMIT 5; + +SELECT title, length +FROM film +ORDER BY length ASC; + +-- GROUP BY (por rating) +-- El número de películas +SELECT rating, COUNT(*) AS numero_peliculas +FROM film +GROUP BY rating; + +-- El precio medio de alquiler +SELECT rating, AVG(rental_rate) AS precio_medio_alquiler +FROM film +GROUP BY rating; + +-- El precio minimo de alquiler +SELECT MIN(rental_rate) AS precio_minimo_alquiler +FROM film; + +-- Añadir un HAVING +SELECT MIN(rental_rate) AS precio_minimo_alquiler_length_110 +FROM film +GROUP BY length +HAVING length > 110; + +--El numero de peliculas y quedate unicamente con aquellos rating que tengan mas de 200 peliculas +SELECT rating, COUNT(*) AS numero_peliculas +FROM film +GROUP BY rating +HAVING COUNT(*) > 200 +ORDER BY numero_peliculas DESC; + +--El precio medio de alquiler y quédate unicamente con aquellos rating que tenga un precio medio superior a 3 +SELECT rating, AVG(rental_rate) AS precio_medio_alquiler +FROM film +GROUP BY (rating) +HAVING AVG(rental_rate) > 3; + +--La duración media de las peliculas y quédate con aquellos rating que tengan una duración media mayor a 115 min +SELECT rating, AVG(length) AS length_media +FROM film +GROUP BY (rating) +HAVING AVG(length) > 115; + +-- Clausula JOIN +SELECT a.first_name AS nombre, b.address AS direccion, c.city as ciudad, d.country as pais +FROM customer a +Left join address b ON b.address_id = a.address_id +Left join city c ON c.city_id = b.city_id +Left join country d ON d.country_id = c.country_id; + +-- Clausula JOIN con SELECT y WHERE -pagina 22 +SELECT TITLE, a.last_name +FROM film f +INNER JOIN film_actor fc ON fc.film_id = f.film_id +INNER JOIN actor a ON fc.actor_id = a.actor_id +WHERE a.last_name like 'C%'; + +-- Cuantos actores tiene cada pelicula? +SELECT f.title AS pelicula, COUNT(a.actor_id) AS numero_actores +FROM film f +INNER JOIN film_actor fc ON fc.film_id = f.film_id +INNER JOIN actor a ON fc.actor_id = a.actor_id +GROUP BY f.title +ORDER BY numero_actores DESC; + +-- Clausula Create Table +CREATE TABLE IF NOT EXISTS public.reviews_ng ( +film_id int2 NOT NULL, +customer_id int2 NOT NULL, +review_date date NOT NULL, +review_description varchar, +CONSTRAINT reviews_pkey PRIMARY KEY (film_id, customer_id)); + +-- Clausula Insert +Insert into public.reviews_ng (film_id, customer_id, review_date, review_description) +values (3, 5, '2024-11-15', 'Es fascinante'); + +--Clausula Update +UPDATE public.reviews_ng +SET review_description = 'La película es bastante buena' +WHERE customer_id = 5 and film_id = 3; + +DELETE +FROM public.reviews_ng; \ No newline at end of file diff --git a/ALUMNOS/MDAA/JUAN_BESSINI/SQL/Bessini-SQL-Part2-ED1.txt b/ALUMNOS/MDAA/JUAN_BESSINI/SQL/Bessini-SQL-Part2-ED1.txt new file mode 100644 index 000000000..8579d5473 --- /dev/null +++ b/ALUMNOS/MDAA/JUAN_BESSINI/SQL/Bessini-SQL-Part2-ED1.txt @@ -0,0 +1,179 @@ +-- Clausula Create Table +--CREATE TABLE IF NOT EXISTS public.reviews_ng ( +--film_id int2 NOT NULL, +--customer_id int2 NOT NULL, +--review_date date NOT NULL, +--review_description varchar, +--CONSTRAINT reviews_pkey PRIMARY KEY (film_id, customer_id)); + +-- Clausula Alter Table - Añadir una nueva columna a la tabla de reviews. Por ejemplo, numero de estrellas que le darias a una pelicula. Llamalo "review_starts" y con datatype int2 +--ALTER TABLE public.reviews_ng +--ADD COLUMN review_stars int2; + +-- Renombrar una columna +--ALTER TABLE public.reviews_ng +--RENAME COLUMN review_description TO review_opinion; + +--Crear vistas +--CREATE VIEW my_view_of_actor AS +--SELECT actor_id, first_name, last_name, last_update +--FROM public.actor +--where first_name is not null; + +--Hacer un IF +select length, +case when length > 100 then 'Pelicula_larga' +when length > 50 and length < 99 then 'Pelicula_media' +else 'pelicula_corta' end +from film; + +--Crea una vista: Mejor comprador (customer) +--CREATE OR REPLACE VIEW top_customers AS +SELECT + c.customer_id, + c.first_name AS customer_name, + SUM(p.amount) AS total_spent +FROM + customer c +JOIN + payment p ON c.customer_id = p.customer_id +GROUP BY + c.customer_id, c.first_name +ORDER BY + total_spent DESC; + +SELECT * FROM top_customers; + +--Crea una vista: Mejor comprador (customer) y añade tiempo que tardan en devolver +CREATE OR REPLACE VIEW top_customers AS +SELECT + c.customer_id, + c.first_name AS customer_name, + SUM(p.amount) AS total_spent, + AVG(DATE_PART('day', r.return_date - r.rental_date)) AS avg_days_to_return +FROM + customer c +JOIN + payment p ON c.customer_id = p.customer_id +JOIN + rental r ON c.customer_id = r.customer_id +WHERE + r.return_date IS NOT NULL -- Solo considerar devoluciones completadas +GROUP BY + c.customer_id, c.first_name +ORDER BY + total_spent DESC; +SELECT * FROM top_customers; + +-- View de los mejores customers +SELECT * +FROM top_customers +LIMIT 5; + +--View de los peores customers (ojo que hay productos cartesianos...) +SELECT * +FROM top_customers +ORDER BY total_spent ASC +LIMIT 5; + +-- View down5 (bien hecha) +CREATE or REPLACE VIEW down5 AS +select concat(first_name, ' ', last_name) as nombre_completo, sum(p.amount) +from payment p +inner join customer c on c.customer_id = p.customer_id +group by 1 +order by 2 desc +limit 5; + +-- View top5 (bien hecha) +CREATE or REPLACE VIEW top5 AS +select concat(first_name, ' ', last_name) as nombre_completo, sum(p.amount) +from payment p +inner join customer c on c.customer_id = p.customer_id +group by 1 +order by 2 asc +limit 5; + +select * from down5 +union all +select * from top5; + +--KPis +--create or replace view kpis as +--select avg(down5.suma_amount), 'down5' as tipo from down5 +--union all +--select avg(top5.suma_amount), 'top5' as tipo from top5; +--select * from kpis + +-- Ejemplos Subconsulta: conteo alquileres, suma amount, rental_duration > 3 dias +SELECT + customer_id, + COUNT(*) AS rental_count, + SUM(amount) AS total_amount, + AVG(rental_duration) AS avg_rental_duration +FROM ( + SELECT + r.customer_id, + p.amount, + DATE_PART('day', r.return_date - r.rental_date) AS rental_duration + FROM + rental r + JOIN + payment p ON r.rental_id = p.rental_id + WHERE + r.return_date IS NOT NULL +) subquery +WHERE rental_duration > 3 +GROUP BY customer_id +ORDER BY total_amount DESC; + +-- Ejemplos Subconsulta +with my_sub_query as +(SELECT title, rental_rate, replacement_cost, round(replacement_cost / rental_rate, 2) as new_column +FROM public.film), +new_1 as +(SELECT title, rental_rate, replacement_cost, round(replacement_cost / rental_rate, 2) as new_column +FROM public.film) +select * from new_1 where title = 'Ali Forever'; + + +--Ejemplo WITH - Clientes que pagan + de 190 (1) +WITH clientes_que_pagan_mas_de_190 AS ( + SELECT customer_id, SUM(amount) AS total_pagado + FROM payment + GROUP BY customer_id + HAVING SUM(amount) > 190 +) +SELECT + SUM(total_pagado) AS suma_total_amount, + COUNT(customer_id) AS numero_clientes +FROM clientes_que_pagan_mas_de_190; + +--Ejemplo WITH - Clientes que pagan + de 190 (2) alternativa a (1) +with sub as +(select customer_id, sum(amount) as total +from payment p +group by customer_id +) +select * from sub where total >190; + +-- Empleado del mes +SELECT staff_id, COUNT(*) AS total_payments +FROM payment +GROUP BY staff_id +ORDER BY total_payments DESC +LIMIT 1; + +-- Empleado del mes - ¿Donde vive (ciudad)? ¿Cuantos clientes ha atendido (conteo por staff)? +WITH empleado_del_mes AS ( + SELECT staff_id, COUNT(*) AS total_payments + FROM payment + GROUP BY staff_id + ORDER BY total_payments DESC + LIMIT 1 +) +SELECT e.staff_id, s.first_name, s.last_name, a.address, a.district, c.city, a.postal_code +FROM empleado_del_mes e +JOIN staff s ON e.staff_id = s.staff_id +JOIN address a ON s.address_id = a.address_id +JOIN city c ON a.city_id = c.city_id; diff --git a/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/Dockerfile b/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/Dockerfile new file mode 100644 index 000000000..41f0d3b54 --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/Dockerfile @@ -0,0 +1,5 @@ +FROM python:3.14.0a2-alpine3.20 +WORKDIR /Ahorcado +COPY ahorcado.py /Ahorcado +COPY palabras.txt /Ahorcado +ENTRYPOINT ["python", "ahorcado.py","palabras.txt"] \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/ahorcado.py b/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/ahorcado.py new file mode 100644 index 000000000..a8994b53b --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/ahorcado.py @@ -0,0 +1,67 @@ +import sys +import pg8000.native +from datetime import datetime + +# nos conectamos a pgadmin +con = pg8000.native.Connection("postgres",password="Welcome01", host="postgres") + +# creamos abecedario +abc = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","Ñ","O","P","Q","R","S","T","U","V","W","X","Y","Z"] + +# creamos listado de palabras desde el txt que pongamos como argumento +with open(sys.argv[1]) as archivo: + palabras = archivo.read().splitlines() + +# definimos las variables que necesitaremos luego +intentos = 0 +aciertos = 0 +fallos = 0 + +# creamos la tabla por si no existe +con.run( + """CREATE TABLE IF NOT EXISTS public.ahorcado( + palabra character varying(50) COLLATE pg_catalog."default" NOT NULL, + letras_acertadas character varying(50) COLLATE pg_catalog."default" NOT NULL, + letras_falladas character varying(50) COLLATE pg_catalog."default" NOT NULL, + intentos integer NOT NULL, + fecha timestamp without time zone NOT NULL + )""") + +# vaciamos la tabla para que esté limpia para nuevos registros +con.run ("delete from public.ahorcado") + +for palabra in palabras: + # definición de variables + letras = len(palabra) + letra_acertada = "" + letra_fallada = "" + + for letra in abc: # bucle por palabra de cada letra del abecedario + if letras > 0: + fecha = datetime.now() # definimos cuándo se hace cada intento para meterlo en la tabla + intentos = intentos + 1 + if letra in palabra: + aciertos = aciertos + 1 # contamos los aciertos + letras = letras - palabra.count(letra) # vamos restando las letras acertadas de cada palabra + letra_acertada = letra_acertada + letra # concatenamos las letras que han pasado por aciertos + else: + fallos = fallos + 1 # contamos los fallos + letra_fallada = letra_fallada + letra # concatenamos las letras que han pasado por fallos + # código sql para que meta los datos en la tabla + con.run("insert into public.ahorcado values (:palabra, :letras_acertadas, :letras_falladas, :intentos, :tiempo)", palabra=palabra, letras_acertadas=letra_acertada, letras_falladas=letra_fallada, intentos=intentos, tiempo=fecha) + +# comprobamos los registros: +primer_registro = con.run ("select min(fecha) from public.ahorcado") +ultimo_registro = con.run ("select max(fecha) from public.ahorcado") + +# extraemos los objetos datetime de las listas +primer_registro_datetime = primer_registro[0][0] +ultimo_registro_datetime = ultimo_registro[0][0] + +# formateamos las fechas +primer_registro_str = primer_registro_datetime.strftime("el día %d/%m/%Y a las %H:%M:%S") +ultimo_registro_str = ultimo_registro_datetime.strftime("el día %d/%m/%Y a las %H:%M:%S") + +# mostramos el resultado +print(f"De {intentos} intentos, hay {aciertos} aciertos y {fallos} fallos.") +print(f"El primer registro es {primer_registro_str} y el último es {ultimo_registro_str}") \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/docker-compose.yml b/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/docker-compose.yml new file mode 100644 index 000000000..adc1478ff --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/docker-compose.yml @@ -0,0 +1,43 @@ +services: + postgres: + container_name: postgres_container + image: postgres:12.1 + environment: + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-Welcome01} + PGDATA: /data/postgres + volumes: + - postgres:/data/postgres + ports: + - "5432:5432" + networks: + - postgres + restart: unless-stopped + + pgadmin: + container_name: pgadmin_container + image: dpage/pgadmin4:4.16 + environment: + PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-pgadmin4@pgadmin.org} + PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin} + volumes: + - pgadmin:/root/.pgadmin + ports: + - "${PGADMIN_PORT:-5050}:80" + networks: + - postgres + restart: unless-stopped + + ahorcado: + build: . + container_name: ahorcado_container + networks: + - postgres + +networks: + postgres: + driver: bridge + +volumes: + postgres: + pgadmin: \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/palabras.txt b/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/palabras.txt new file mode 100644 index 000000000..09bf5cb3b --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/AHORCADO/palabras.txt @@ -0,0 +1,10 @@ +MURCIELAGO +VIAJE +EVADIR +ZAPATO +CIELO +RECREO +PIZARRA +MATEMATICAS +PROGRAMACION +ORDENADOR \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/DOCKER/Dockerfile b/ALUMNOS/MDAA/MAR_SOLER/DOCKER/Dockerfile new file mode 100644 index 000000000..12e4573b9 --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/DOCKER/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:latest + +RUN apt-get update && apt-get install -y python3 + +WORKDIR /app + +COPY suma.py /app/suma.py + +ENTRYPOINT ["python3", "suma.py" ] \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/DOCKER/prueba-docker.png b/ALUMNOS/MDAA/MAR_SOLER/DOCKER/prueba-docker.png new file mode 100644 index 000000000..bde79c625 Binary files /dev/null and b/ALUMNOS/MDAA/MAR_SOLER/DOCKER/prueba-docker.png differ diff --git a/ALUMNOS/MDAA/MAR_SOLER/DOCKER/suma.py b/ALUMNOS/MDAA/MAR_SOLER/DOCKER/suma.py new file mode 100644 index 000000000..b8beba638 --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/DOCKER/suma.py @@ -0,0 +1,25 @@ +""" +1. Construir un script en python que acepte dos números como parámetros e imprima el resultado de la suma +2. Construir una imagen docker que contenga dicho python script +3. Cuando se ejecute el contendor docker, este debe invocar al script pasando como parámetro ambos números. + +Ejemplo de invocación del contenedor Docker +docker run pysum 3 4 + +Ejemplo de salida del resultado esperado +Sum: 7 + +""" + +import sys + +def suma (num1,num2): + print(f'La suma de {num1} y {num2} es {num1 + num2}') + +if len(sys.argv) != 3: + print("Introduce dos números de una cifra cada uno") + +else: + num1 = int(sys.argv[1]) + num2 = int(sys.argv[2]) + suma(num1, num2) \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/KAFKA/consumer.py b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/consumer.py new file mode 100644 index 000000000..e5d61fdd5 --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/consumer.py @@ -0,0 +1,31 @@ +from confluent_kafka import Consumer, KafkaError + +config = { + 'bootstrap.servers': 'localhost:9092', + 'group.id': 'python-consumer-group', + 'auto.offset.reset': 'earliest' +} + +consumer = Consumer(config) + +topic = "recetas" +consumer.subscribe([topic]) + +try: + while True: + msg = consumer.poll(1.0) # Lee nuevos mensajes cada 1 segundo + + if msg is None: + continue + if msg.error(): + if msg.error().code() == KafkaError._PARTITION_EOF: + print("No hay más mensajes en esta partición.") + else: + print("Error al recibir mensaje: {}".format(msg.error())) + else: + print("Nuevo mensaje: {}".format(msg.value().decode("utf-8"))) + +except KeyboardInterrupt: + pass +finally: + consumer.close() \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/KAFKA/docker-compose.yml b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/docker-compose.yml new file mode 100644 index 000000000..a266b11d0 --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/docker-compose.yml @@ -0,0 +1,150 @@ +--- +version: '3.5' +services: + zookeeper: + image: confluentinc/cp-zookeeper:latest + environment: + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + ports: + - 2181:2181 + kafka: + image: confluentinc/cp-kafka:7.3.3 + depends_on: + - zookeeper + ports: + - 9092:9092 + environment: + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + kafka-ui: + image: provectuslabs/kafka-ui:latest + container_name: kafka-ui-3 + depends_on: + - kafka + ports: + - "8080:8080" + restart: always + environment: + - KAFKA_CLUSTERS_0_NAME=base + - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:29092 + ksql-server: + image: confluentinc/cp-ksql-server:latest + depends_on: + - kafka + ports: + - 8088:8088 + environment: + KSQL_BOOTSTRAP_SERVERS: kafka:29092 + KSQL_LISTENERS: http://0.0.0.0:8088 + ksql-cli: + image: confluentinc/cp-ksql-cli:latest + depends_on: + - ksql-server + entrypoint: /bin/sh + tty: true + + kafka-connect: + image: confluentinc/cp-kafka-connect:7.3.3 + depends_on: + - kafka + - schema-registry + - postgres + environment: + CONNECT_PLUGIN_PATH: /usr/share/java,/usr/share/confluent-hub-components + CONNECT_BOOTSTRAP_SERVERS: kafka:29092 + CONNECT_REST_ADVERTISED_HOST_NAME: connect + CONNECT_GROUP_ID: compose-connect-group + CONNECT_CONFIG_STORAGE_TOPIC: docker-connect-configs + CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR: 1 + CONNECT_OFFSET_FLUSH_INTERVAL_MS: 10000 + CONNECT_OFFSET_STORAGE_TOPIC: docker-connect-offsets + CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR: 1 + CONNECT_STATUS_STORAGE_TOPIC: docker-connect-status + CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: 1 + CONNECT_KEY_CONVERTER: org.apache.kafka.connect.storage.StringConverter + CONNECT_VALUE_CONVERTER: org.apache.kafka.connect.storage.StringConverter + CONNECT_VALUE_CONVERTER_SCHEMA_REGISTRY_URL: http://schema-registry:8081 + # CLASSPATH required due to CC-2422 + CLASSPATH: /usr/share/java/monitoring-interceptors/monitoring-interceptors-7.3.3.jar + CONNECT_PRODUCER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringProducerInterceptor" + CONNECT_CONSUMER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringConsumerInterceptor" + CONNECT_LOG4J_LOGGERS: org.apache.zookeeper=ERROR,org.I0Itec.zkclient=ERROR,org.reflections=ERROR + command: + - bash + - -c + - | + confluent-hub install confluentinc/kafka-connect-jdbc:10.7.4 + /etc/confluent/docker/run + + schema-registry: + image: confluentinc/cp-schema-registry:7.3.3 + hostname: schema-registry + container_name: schema-registry + depends_on: + - kafka + ports: + - "8081:8081" + environment: + SCHEMA_REGISTRY_HOST_NAME: schema-registry + SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: 'kafka:29092' + SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8081 + + + control-center: + image: confluentinc/cp-enterprise-control-center:7.3.3 + hostname: control-center + container_name: control-center + depends_on: + - kafka + - schema-registry + - kafka-connect + - ksql-server + ports: + - "9021:9021" + environment: + CONTROL_CENTER_BOOTSTRAP_SERVERS: 'kafka:29092' + CONTROL_CENTER_CONNECT_CONNECT-DEFAULT_CLUSTER: 'kafka-connect:8083' + CONTROL_CENTER_KSQL_KSQLDB1_URL: "http://ksql-server:8088" + CONTROL_CENTER_KSQL_KSQLDB1_ADVERTISED_URL: "http://localhost:8088" + CONTROL_CENTER_SCHEMA_REGISTRY_URL: "http://schema-registry:8081" + CONTROL_CENTER_REPLICATION_FACTOR: 1 + CONTROL_CENTER_INTERNAL_TOPICS_PARTITIONS: 1 + CONTROL_CENTER_MONITORING_INTERCEPTOR_TOPIC_PARTITIONS: 1 + CONFLUENT_METRICS_TOPIC_REPLICATION: 1 + CONTROL_CENTER_CONNECT_HEALTHCHECK_ENDPOINT: '/connectors' + PORT: 9021 + + postgres: + container_name: postgres_container + image: postgres:12.1 + environment: + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-Welcome01} + PGDATA: /data/postgres + volumes: + - postgres:/data/postgres + ports: + - "5432:5432" + restart: unless-stopped + + pgadmin: + container_name: pgadmin_container + image: dpage/pgadmin4:4.16 + environment: + PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-pgadmin4@pgadmin.org} + PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin} + volumes: + - pgadmin:/root/.pgadmin + ports: + - "${PGADMIN_PORT:-5050}:80" + restart: unless-stopped + + +volumes: + postgres: + pgadmin: \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/KAFKA/pom.xml b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/pom.xml new file mode 100644 index 000000000..3ed63634e --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.gft.dlp.kafka + lab03 + 1.0-SNAPSHOT + + + 1.8 + 1.8 + + + + + + org.apache.kafka + kafka_2.13 + 2.4.0 + + + org.apache.kafka + kafka-streams + 2.4.0 + + + com.github.javafaker + javafaker + 1.0.2 + + + + io.confluent + common-utils + 4.1.0 + + + org.slf4j + slf4j-api + 1.7.5 + + + org.slf4j + slf4j-log4j12 + 1.7.5 + + + + + confluent + https://packages.confluent.io/maven/ + + + \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/KAFKA/producer.py b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/producer.py new file mode 100644 index 000000000..1289a6243 --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/producer.py @@ -0,0 +1,31 @@ +import time +from json import dumps +from confluent_kafka import Producer +import re + +config = { + 'bootstrap.servers': 'localhost:9092', + 'client.id': 'python-producer' +} + +producer = Producer(config) + +topic_kafka = "recetas" + +file1 = open("recetas.txt",encoding="utf8") +Lines = file1.readlines() + +count = 0 + +for line in Lines: + time.sleep(2) + print( line.strip() + "\n") + words = re.findall(r"[\w']+|[.,!?;]", line) + for word in words: + data_bytes = word + key = str(count) + producer.produce(topic=topic_kafka, value=data_bytes, key=key) + producer.flush() + +if producer.flush() != 0: + print("Error en el envío de algunos mensajes.") \ No newline at end of file diff --git a/ALUMNOS/MDAA/MAR_SOLER/KAFKA/recetas.txt b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/recetas.txt new file mode 100644 index 000000000..cdc83ba1d --- /dev/null +++ b/ALUMNOS/MDAA/MAR_SOLER/KAFKA/recetas.txt @@ -0,0 +1,100 @@ +Paella Valenciana +Tacos al Pastor +Enchiladas Verdes +Pizza Margarita +Sushi de Salmón +Hamburguesa Clásica +Lasagna Boloñesa +Ceviche Peruano +Empanadas de Carne +Falafel con Hummus +Gazpacho Andaluz +Moussaka Griega +Pad Thai +Ratatouille +Biryani de Pollo +Chili con Carne +Croquetas de Jamón +Pollo a la Parrilla +Sopa de Tomate +Risotto de Champiñones +Filete de Ternera +Pescado a la Plancha +Ensalada César +Tortilla Española +Arroz con Leche +Sopa de Mariscos +Pollo al Ajillo +Pasta Carbonara +Pan de Ajo +Curry Vegetariano +Guiso de Lentejas +Empanadas de Pollo +Pollo a la Cacciatora +Fajitas de Res +Bacalao a la Vizcaína +Crema de Calabaza +Quiche Lorraine +Macarrones con Queso +Burrito Mexicano +Sándwich Cubano +Tarta de Queso +Churros con Chocolate +Pollo al Curry +Arroz Frito +Sushi de Atún +Pato a la Naranja +Minestrone +Canelones de Espinacas +Mousse de Chocolate +Panna Cotta +Pisto Manchego +Croissant de Jamón y Queso +Sopa de Ajo +Goulash Húngaro +Bruschetta Italiana +Focaccia de Romero +Paella Mixta +Pollo a la Barbacoa +Carne Asada +Chili Vegetariano +Lasaña de Verduras +Sushi Vegetariano +Bocadillo de Calamares +Ensalada Caprese +Steak Tartare +Pollo al Horno +Crepes Suzette +Pollo al Chipotle +Pastel de Carne +Tortilla de Patatas +Patatas Bravas +Salmón al Horno +Albóndigas en Salsa +Ensalada Griega +Calamares a la Romana +Pechuga de Pollo Rellena +Ensalada de Quinoa +Pasta al Pesto +Croquetas de Pollo +Fideos de Arroz con Verduras +Empanada Gallega +Tiramisú +Panqueques Americanos +Chili de Quinoa +Brócoli al Ajillo +Nuggets de Pollo Caseros +Puré de Papas +Crema de Champiñones +Pizza Pepperoni +Pollo con Verduras +Espaguetis al Pesto +Ensalada Mixta +Canelones de Carne +Gambas al Ajillo +Risotto de Mariscos +Merluza en Salsa Verde +Ensalada de Pasta +Pechuga a la Plancha +Lomo Saltado +Pastel de Chocolate \ No newline at end of file diff --git a/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/Dockerfile b/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/Dockerfile new file mode 100644 index 000000000..52c444304 --- /dev/null +++ b/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-alpine + +WORKDIR /app + +COPY suma.py /app/suma.py + +ENTRYPOINT ["python", "/app/suma.py"] \ No newline at end of file diff --git a/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/captura_ejecucion_docker.png b/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/captura_ejecucion_docker.png new file mode 100644 index 000000000..67fa3b3b0 Binary files /dev/null and b/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/captura_ejecucion_docker.png differ diff --git a/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/imagen_dockerhub.txt b/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/imagen_dockerhub.txt new file mode 100644 index 000000000..26eccbc89 --- /dev/null +++ b/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/imagen_dockerhub.txt @@ -0,0 +1,3 @@ +https://hub.docker.com/repository/docker/migueltocu/pysum/tags + +docker pull migueltocu/pysum:latest \ No newline at end of file diff --git a/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/suma.py b/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/suma.py new file mode 100644 index 000000000..b0a9b7176 --- /dev/null +++ b/ALUMNOS/MDAA/MIGUEL_TORRES/DOCKER/suma.py @@ -0,0 +1,17 @@ +import sys + +def main(): + if len(sys.argv) != 3: + print("Uso: python script.py ") + sys.exit(1) + + try: + num1 = int(sys.argv[1]) + num2 = int(sys.argv[2]) + print(f"Suma: {num1 + num2}") + except ValueError: + print("Error: Los dos argumentos deben ser números enteros.") + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/ALUMNOS/MDAA/MIGUEL_TORRES/SQL/sesion1.sql b/ALUMNOS/MDAA/MIGUEL_TORRES/SQL/sesion1.sql new file mode 100644 index 000000000..47f71c10b --- /dev/null +++ b/ALUMNOS/MDAA/MIGUEL_TORRES/SQL/sesion1.sql @@ -0,0 +1,168 @@ +select * +from actor +where first_name like 'A%'; + +select title +from film +where rental_rate >10; + +select * +from film +where rental_rate between 5 and 10; + +select * +from film +where rental_rate <5 +and rental_duration <100; + +select rental_rate +from film +where title='Giant Troopers'; + +select rating +from film +where title like 'Ali%' +and rental_duration; + +select title +from film +order by rental_duration desc; + +select lenght +from film as f +order by lenght desc +limit 5; + + +select rental_rate, count(*) +from film +group by rental_rate; + +--Ejercicio +SELECT rating, + count(title), + round(avg(rental_rate),2) as Precio_medio, + min(rental_rate), + max(rental_rate), + round(avg(length),2) as Duracion_media, + max(release_year), + min(release_year) +FROM film +GROUP BY rating; + + +--Ejercicio 2 +SELECT rating, + count(title), + round(avg(rental_rate),2) as Precio_medio, + min(rental_rate), + max(rental_rate), + round(avg(length),2) as Duracion_media, + max(release_year), + min(release_year) +FROM film +GROUP BY rating +HAVING avg(length) >110; + +--Ejercicio 3 + +SELECT rating, + count(title) as Total_peliculas, + round(avg(rental_rate),2)as Precio_medio, + round(avg(length),2) as Duracion_media +FROM film +GROUP BY rating +HAVING count(title) >200 +and avg(rental_rate)>3 +and avg(length) >115; + +--Ejercicios Joins + +select upper(c.first_name),upper(last_name), a.address +From customer c +left join address a on c.address_id=a.address_id; + +--Ejercicio +select upper(c.first_name),upper(last_name), a.address, d.city, e.country +From customer c +left join address a on c.address_id=a.address_id +left join city d on a.city_id=d.city_id +left join country e on d.country_id=e.country_id + + +--Ejercicio + +SELECT f.title, a.first_name, a.last_name +FROM film f +left join film_actor fa on f.film_id=fa.film_id +left join actor a on fa.actor_id=a.actor_id +where a.last_name like 'C%'; + +--Ejercicio dificil + +SELECT f.title, count(a.actor_id) +FROM film f +left join film_actor fa on f.film_id=fa.film_id +left join actor a on fa.actor_id=a.actor_id +where a.last_name like 'C%' +Group by 1 +having count(a.actor_id)=1; + +--Ejercicios + +SELECT f.title, count(a.actor_id) as actor_account +FROM film f +left join film_actor fa on f.film_id=fa.film_id +left join actor a on fa.actor_id=a.actor_id +Group by f.title +order by actor_account desc; + +SELECT f.title, count(a.actor_id) as Actores_Totales +FROM film f +left join film_actor fa on f.film_id=fa.film_id +left join actor a on fa.actor_id=a.actor_id +Group by f.title +having count(a.actor_id)>2 +order by Actores_Totales desc; + + +SELECT f.title, count(a.actor_id) as Max_actors +FROM film f +left join film_actor fa on f.film_id=fa.film_id +left join actor a on fa.actor_id=a.actor_id +group by f. title +order by Max_actors desc +limit 1; + + +--Crear tabla + +CREATE TABLE IF NOT EXISTS public.reviews ( +film_id integer NOT NULL, +customer_id integer NOT NULL, +review_date timestamp not null default now(), +review_description varchar(50), +CONSTRAINT reviews_pkey PRIMARY KEY (film_id, customer_id) + ); + +select * +from reviews; + +--Añadir valores +INSERT INTO reviews (film_id, customer_id, review_description) +values(1, 1,'Muy buena pelicula' ); + +--Update + +update reviews +set review_description ='Es muy mala' +where film_id=1; + +--Delete parte de una tabla + +delete +from reviews +where review_description='Es muy mala' + +--Borrar tabla +drop table public.reviews \ No newline at end of file diff --git a/ALUMNOS/MDAA/MIGUEL_TORRES/SQL/sesion2.sql b/ALUMNOS/MDAA/MIGUEL_TORRES/SQL/sesion2.sql new file mode 100644 index 000000000..bf6c0a624 --- /dev/null +++ b/ALUMNOS/MDAA/MIGUEL_TORRES/SQL/sesion2.sql @@ -0,0 +1,137 @@ +select * +from film; + + +SELECT f.title, count(a.actor_id) as actor_account +FROM film f +left join film_actor fa on f.film_id=fa.film_id +left join actor a on fa.actor_id=a.actor_id +Group by f.title +order by actor_account desc; + +--Dia 2 + +CREATE TABLE IF NOT EXISTS public.reviews ( +film_id integer NOT NULL, +customer_id integer NOT NULL, +review_date timestamp not null default now(), +review_description varchar(50), +CONSTRAINT reviews_pkey PRIMARY KEY (film_id, customer_id) + ); + +--Añadir columna +alter table REVIEWS +add Reviews_stars int2; + +alter table reviews +rename column review_description +to review_opinion; + +select * +from reviews; + + +--Cambiar tipo de dato + +alter table reviews +alter column review_opinion type varchar(25); + + +--VIEWS + +select * +from actor_info ai + +create or replace view antoni_molla as +select f.title, a.first_name, a.last_name +from film f +left join film_actor fa on f.film_id=fa.film_id +left join actor a on fa.actor_id=a.actor_id; + + +select * +from antoni_molla am; + + +--Top 5 +create or replace view Top5 as +select concat(c.first_name,'',c.last_name),sum(p.amount) as suma_amount, avg(r.return_date-r.rental_date) as rental_duration, +count(i.film_id) +from customer c +left join payment p on c.customer_id=p.customer_id +left join rental r on p.rental_id=r.rental_id +LEFT JOIN inventory i on r.inventory_id=i.inventory_id +group by 1 +order by sum(p.amount) desc +limit 5; + + +--Peores clientes + +create view Down5 as +select concat(c.first_name, ' ',c.last_name),sum(p.amount) as suma_amount, avg(r.return_date-r.rental_date) as rental_duration, +count(i.film_id) +from customer c +left join payment p on c.customer_id=p.customer_id +left join rental r on p.rental_id=r.rental_id +LEFT JOIN inventory i on r.inventory_id=i.inventory_id +group by 1 +order by sum(p.amount) asc +limit 5; + +select * +from peoresclientes p + +select * from Down5 +union all +select * from top5 t + +create view kpis as +select avg(Down5.suma_amount), 'down5' as tipo from Down5 +union all +select avg(top5.suma_amount), 'top5' as tipo from top5 + + +-Fechas y cambios de datos +SELECT avg(return_date::date-rental::date) AS difference_in_days, +return_date::date, rental_date::date, rental_id::varchar +FROM rental r; + + +SELECT avg(return_Date::date-rental_date::date)AS difference_in_days +FROM rental r; + + +--Subconsultas + +select sum(p.amount) from payment p +where customer_id in ( +select customer_id from customer c where first_name ilike 'C%') + + + + +select sum(p.amount), count(rental_id), sum(p.amount)/count(rental_id) as Tiket_Medio from payment p +where customer_id in ( +select customer_id from rental where return_date::date-rental_date::date>3) + + +--Clausula with + + +with my_sub_query as +(select customer_id, sum(amount) as total +from payment p +group by 1) +select * from my_sub_query where total > 190; + + + +with my_sub_query as +(select concat(first_name,'', last_name), +from staff s +left join payment p on s.staff_id=p.staff_id +group by 1 +limit 1) +select * from sub +order by payment.amount \ No newline at end of file diff --git a/ALUMNOS/MDAB/ALEJANDRO_BOSCH/CHUCK/docker-compose.yml b/ALUMNOS/MDAB/ALEJANDRO_BOSCH/CHUCK/docker-compose.yml new file mode 100644 index 000000000..50b5ba65b --- /dev/null +++ b/ALUMNOS/MDAB/ALEJANDRO_BOSCH/CHUCK/docker-compose.yml @@ -0,0 +1,82 @@ +version: '3.8' + +services: + nifi: + image: apache/nifi:1.27.0 + container_name: nifi + restart: always + ports: + - 8443:8443 + environment: + - SINGLE_USER_CREDENTIALS_USERNAME=admin + - SINGLE_USER_CREDENTIALS_PASSWORD=ctsBtRBKHRAx69EqUghvvgEvjnaLjFEB + volumes: + - ./data:/tmp/data + user: "0:0" + networks: + - postgres + + mongo: + image: mongo + restart: always + ports: + - 27017:27017 + environment: + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: example + volumes: + - mongo_data:/data/db + networks: + - postgres + + mongo-express: + image: mongo-express + restart: always + ports: + - 8081:8081 + environment: + ME_CONFIG_MONGODB_ADMINUSERNAME: root + ME_CONFIG_MONGODB_ADMINPASSWORD: example + ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/ + networks: + - postgres + + postgres: + container_name: postgres_container + image: postgres:12.1 + environment: + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-Welcome01} + PGDATA: /data/postgres + volumes: + - postgres:/data/postgres + ports: + - "5432:5432" + networks: + - postgres + restart: unless-stopped + + pgadmin: + container_name: pgadmin_container + image: dpage/pgadmin4:4.16 + environment: + PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-pgadmin4@pgadmin.org} + PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin} + volumes: + - pgadmin:/root/.pgadmin + ports: + - "${PGADMIN_PORT:-5050}:80" + networks: + - postgres + restart: unless-stopped + +networks: + postgres: + driver: bridge + +volumes: + postgres: + pgadmin: + mongo_data: + data: + db_data: diff --git a/ALUMNOS/MDAB/ALEJANDRO_BOSCH/CHUCK/main.py b/ALUMNOS/MDAB/ALEJANDRO_BOSCH/CHUCK/main.py new file mode 100644 index 000000000..2e3253b36 --- /dev/null +++ b/ALUMNOS/MDAB/ALEJANDRO_BOSCH/CHUCK/main.py @@ -0,0 +1,47 @@ +from pymongo import MongoClient +import psycopg2 + +# Conexión a MongoDB (usa la base de datos 'chuck' y la colección 'chistes') +mongo_client = MongoClient('mongodb://root:example@localhost:27017') +mongo_db = mongo_client['chuck'] +mongo_collection = mongo_db['chistes'] + +# Conexión a PostgreSQL (usa el dbname que se infiere de docker-compose, en este caso 'postgres') +conn = psycopg2.connect( + dbname="postgres", + user="postgres", + password="Welcome01", + host="localhost", + port="5432" +) +cur = conn.cursor() + +# Crear la tabla 'jokes' si no existe, con 'value' como VARCHAR y 'created_at' como TIMESTAMP +crear_tabla = """ +CREATE TABLE IF NOT EXISTS jokes ( + value VARCHAR, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +""" +cur.execute(crear_tabla) +conn.commit() + +# Recuperar los documentos de la colección 'chistes' +resultado = mongo_collection.find() + +# Por cada documento, insertar cada palabra del campo "value" en la tabla 'jokes' +for chiste in resultado: + if "value" in chiste: + palabras = chiste["value"].split() + for palabra in palabras: + insertar = """ + INSERT INTO jokes (value) + VALUES (%s); + """ + cur.execute(insertar, (palabra,)) + +conn.commit() +cur.close() +conn.close() + +print("Datos insertados correctamente.") diff --git a/ALUMNOS/MDAB/ALEJANDRO_BOSCH/CHUCK/nifi_template.xml b/ALUMNOS/MDAB/ALEJANDRO_BOSCH/CHUCK/nifi_template.xml new file mode 100644 index 000000000..a63e9396a --- /dev/null +++ b/ALUMNOS/MDAB/ALEJANDRO_BOSCH/CHUCK/nifi_template.xml @@ -0,0 +1,1115 @@ + +