Oracle_One-Alura_Latam/011_mysql/proyecto_mysql.md

462 lines
10 KiB
Markdown
Raw Permalink Normal View History

2023-10-29 03:55:17 -03:00
# Proyecto Empresa
#### Entidades
- **Cliente**
- **Vendedor**
- **Producto**
- **Factura**
- **Items**
<style>div.mermaid{text-align: center;}</style>
```mermaid
erDiagram
Producto {
CODIGO varchar PK
DESCRIPCION varchar
SABOR varchar
TAMANO varchar
ENVASE varchar
PRECIO_LISTA float
}
Vendedor {
MATRICULA varchar PK
NOMBRE varchar
BARRIO varchar
COMISION float
FECHA_ADMISION date
VACACIONES bit
}
Cliente {
DNI varchar PK
NOMBRE varchar
BARRIO varchar
CIUDAD varchar
ESTADO varchar
FECHA_NACIMIENTO date
EDAD int
SEXO varchar
LIMITE_CREDITO int
VOLUMEN_COMPRA int
PRIMERA_COMPRA bit
}
Factura {
NUMERO varchar PK
DNI varchar FK
FECHA date
MATRICULA varchar FK
IMPUESTO float
}
Items {
CODIGO varchar FK
PRECIO float
CANTIDAD bigint
}
2023-11-26 15:17:11 -03:00
Vendedor ||--|{ Factura : realiza
Cliente ||--|{ Factura : involucra
Producto ||--|{ Items : contiene
Factura ||--|{ Items : posee
2023-10-29 03:55:17 -03:00
```
```sql
CREATE TABLE clientes (
dni VARCHAR(11) NOT NULL,
nombre VARCHAR(100) NULL,
direccion VARCHAR(150),
barrio VARCHAR(50),
ciudad VARCHAR(50),
estado VARCHAR(20),
cp VARCHAR(10),
fecha_nacimiento DATE,
edad SMALLINT,
limite_credito FLOAT,
volumen_compra FLOAT,
primera_compra BIT,
PRIMARY KEY (dni)
);
CREATE TABLE vendedores (
matricula VARCHAR(5) NOT NULL,
nombre VARCHAR(100),
barrio VARCHAR(50),
comision float,
fecha_admision DATE,
vacaciones BIT(1),
PRIMARY KEY (matricula)
);
CREATE TABLE productos (
codigo VARCHAR(10) NOT NULL,
descripcion VARCHAR(100),
sabor VARCHAR(50),
tamano VARCHAR(50),
envase VARCHAR(50),
precio FLOAT,
PRIMARY KEY (codigo)
);
CREATE TABLE facturas (
numero VARCHAR(5) NOT NULL,
fecha DATE,
dni VARCHAR(5) NOT NULL,
matricula VARCHAR(11) NOT NULL,
impuesto FLOAT,
PRIMARY KEY (numero),
FOREIGN KEY (dni) REFERENCES clientes(dni),
FOREIGN KEY (matricula) REFERENCES vendedores(matricula)
);
CREATE TABLE items (
numero VARCHAR(5) NOT NULL,
codigo VARCHAR(10) NOT NULL,
cantidad INT,
precio FLOAT,
PRIMARY KEY (numero, codigo),
FOREIGN KEY (numero) REFERENCES facturas(numero),
FOREIGN KEY (codigo) REFERENCES productos(codigo)
);
```
## Poblar tablas
### Script insertar productos, vendedores y clientes
[insert](./proyecto_scripts/populate_tables.sql)
### Importar registros de facturas e items desde `jugos_ventas`
[./proyecto_scripts/import_records.sql](./proyecto_scripts/import_records.sql)
```sql
USE empresa;
INSERT INTO facturas
SELECT numero, fecha_venta as fecha, dni, matricula, impuesto
FROM jugos_ventas.facturas;
INSERT INTO items
SELECT numero, codigo_del_producto AS codigo, cantidad, precio
FROM jugos_ventas.items_facturas;
```
## Funcion RAND
Devuelve un número aleatorio entre 0 y 1
```sql
SELECT RAND();
+---------------------+
| rand() |
+---------------------+
| 0.20842885617951756 |
+---------------------+
```
```sql
SELECT FLOOR(RAND() * (MAX-MIN+1)+MIN) AS ALEATORIO;
```
```sql
-- MIN = 20, MAX = 250
SELECT FLOOR(RAND() * (250-20+1)+20) AS ALEATORIO;
+-----------+
| ALEATORIO |
+-----------+
| 28 |
+-----------+
-- MIN = 1, MAX = 10
SELECT FLOOR(RAND() * (10-1+1)+1) AS ALEATORIO;
+-----------+
| ALEATORIO |
+-----------+
| 5 |
+-----------+
```
### Funcion número aleatorio
#### Activar creación de funciones
En el caso de MySQL puede ser requerido lo sgte.
```sql
SET GLOBAL log_bin_trust_function_creators = 1;
```
```sql
DROP FUNCTION IF EXISTS f_aleatorio;
DELIMITER $$
CREATE FUNCTION f_aleatorio(min INT, max INT)
RETURNS INT
BEGIN
DECLARE vresultado INT;
SELECT FLOOR(RAND() * (MAX-MIN+1)+MIN) INTO vresultado;
RETURN vresultado;
END $$
DELIMITER ;
```
### Función Cliente Aleatorio
```sql
DROP FUNCTION IF EXISTS f_cliente_aleatorio;
DELIMITER $$
CREATE FUNCTION f_cliente_aleatorio()
RETURNS VARCHAR(11)
BEGIN
DECLARE vresultado VARCHAR(11);
DECLARE vmax, vrand INT;
SELECT COUNT(*) INTO vmax FROM clientes;
SET vrand = f_aleatorio(1, vmax);
SET vrand = vrand-1;
SELECT dni INTO vresultado FROM clientes LIMIT vrand, 1;
RETURN vresultado;
END $$
DELIMITER ;
```
***Crear una función para obtener un producto y otra para obtener un***
***vendedor, usando como base la función `f_aleatorio()`***
#### Función Producto Aleatorio
```sql
DROP FUNCTION IF EXISTS f_producto_aleatorio;
DELIMITER $$
CREATE FUNCTION f_producto_aleatorio()
RETURNS VARCHAR(11)
BEGIN
DECLARE vresultado VARCHAR(11);
DECLARE vmax, vrand INT;
SELECT COUNT(*) INTO vmax FROM productos;
SET vrand = f_aleatorio(1, vmax);
SET vrand = vrand-1;
SELECT codigo INTO vresultado FROM productos LIMIT vrand, 1;
RETURN vresultado;
END $$
DELIMITER ;
```
#### Función Vendedor Aleatorio
```sql
DROP FUNCTION IF EXISTS f_vendedor_aleatorio;
DELIMITER $$
CREATE FUNCTION f_vendedor_aleatorio()
RETURNS VARCHAR(11)
BEGIN
DECLARE vresultado VARCHAR(11);
DECLARE vmax, vrand INT;
SELECT COUNT(*) INTO vmax FROM vendedores;
SET vrand = f_aleatorio(1, vmax);
SET vrand = vrand-1;
SELECT matricula INTO vresultado FROM vendedores LIMIT vrand, 1;
RETURN vresultado;
END $$
DELIMITER ;
```
### Funciones aleatorias
```sql
SELECT f_cliente_aleatorio() AS cliente,
f_producto_aleatorio() AS producto,
f_vendedor_aleatorio() AS vendedor;
+-------------+----------+----------+
| cliente | producto | vendedor |
+-------------+----------+----------+
| 94387575700 | 243083 | 00235 |
+-------------+----------+----------+
```
```sql
DROP PROCEDURE IF EXISTS sp_venta;
DELIMITER $$
CREATE PROCEDURE sp_venta(fecha DATE, max_items INT, max_cantidad INT)
BEGIN
DECLARE vcliente VARCHAR(11);
DECLARE vproducto VARCHAR(10);
DECLARE vvendedor VARCHAR(5);
DECLARE vcantidad INT;
DECLARE vprecio FLOAT;
DECLARE vitems INT;
DECLARE vnfactura INT;
DECLARE vcontador INT DEFAULT 1;
SELECT MAX(numero)+1 INTO vnfactura FROM facturas;
SET vcliente = f_cliente_aleatorio();
SET vvendedor = f_vendedor_aleatorio();
INSERT INTO facturas (numero, fecha, dni, matricula, impuesto)
VALUES (vnfactura, fecha, vcliente, vvendedor, 0.16);
SET vitems = f_aleatorio(1, max_items);
WHILE vcontador <= vitems DO
SET vproducto = f_producto_aleatorio();
SET vcantidad = f_aleatorio(1,max_cantidad);
SELECT precio INTO vprecio FROM productos WHERE codigo = vproducto;
INSERT INTO items(numero, codigo, cantidad, precio)
VALUES(vnfactura, vproducto, vcantidad, vprecio);
SET vcontador = vcontador+1;
END WHILE;
END $$
DELIMITER ;
```
- Script [funciones_y_procedimientos](./proyecto_scripts/funcs_sp.sql)
### Corrigiendo campos numero en tablas `items` y `facturas`
[re_create_tables](./proyecto_scripts/re_create_tables.sql)
```sql
CALL sp_venta('20210619', 3, 100);
Query OK, 27 rows affected (0.023 sec)
select * from facturas
where numero = (select max(numero) from facturas);
+--------+------------+------------+-----------+----------+
| numero | fecha | dni | matricula | impuesto |
+--------+------------+------------+-----------+----------+
| 87977 | 2021-06-19 | 5648641702 | 00236 | 0.16 |
+--------+------------+------------+-----------+----------+
```
***Calcular la facturación para la fecha '20210619'***
```sql
SELECT F.fecha, SUM(I.cantidad*I.precio) AS Facturacion
FROM facturas F
INNER JOIN
items I
ON F.numero = I.numero
WHERE F.fecha = '20210619' GROUP BY F.fecha;
```
***Calcular el valor del impuesto pago por año redondeado al mayor entero***
```sql
SELECT YEAR(fecha) AS "AÑO", CEIL(SUM((cantidad*precio)*impuesto))AS RESULTADO
FROM facturas F
INNER JOIN items I ON F.numero = I.numero
GROUP BY YEAR(fecha);
+------+-----------+
| AÑO | RESULTADO |
+------+-----------+
| 2015 | 4382250 |
| 2016 | 4656938 |
| 2017 | 4879519 |
| 2018 | 1211812 |
| 2021 | 9228 |
+------+-----------+
```
## Triggers INSERT DELETE UPDATE
[Triggers.sql](./proyecto_scripts/triggers.sql.old)
```sql
CREATE TABLE facturacion(
fecha DATE NULL,
venta_total FLOAT
);
DELIMITER //
CREATE TRIGGER tg_facturacion_insert
AFTER INSERT ON items
FOR EACH ROW BEGIN
DELETE FROM facturacion;
INSERT INTO facturacion
SELECT A.FECHA, SUM(B.cantidad * B.precio) AS VENTA_TOTAL
FROM facturas A
INNER JOIN
items B
ON A.NUMERO = B.NUMERO
GROUP BY A.FECHA;
END //
DELIMITER //
CREATE TRIGGER tg_facturacion_delete
AFTER DELETE ON items
FOR EACH ROW BEGIN
DELETE FROM facturacion;
INSERT INTO facturacion
SELECT A.fecha, SUM(B.cantidad * B.precio) AS VENTA_TOTAL
FROM facturas A
INNER JOIN
items B
ON A.numero = B.numero
GROUP BY A.fecha;
END //
DELIMITER //
CREATE TRIGGER tg_facturacion_update
AFTER UPDATE ON items
FOR EACH ROW BEGIN
DELETE FROM facturacion;
INSERT INTO facturacion
SELECT A.fecha, SUM(B.cantidad * B.precio) AS VENTA_TOTAL
FROM facturas A
INNER JOIN
items B
ON A.numero = B.numero
GROUP BY A.fecha;
END //
DELIMITER ;
```
```sql
CALL sp_venta('20210622', 3, 10);
SELECT * FROM facturacion WHERE fecha = '20210622';
+------------+-------------+
| fecha | venta_total |
+------------+-------------+
| 2021-06-22 | 14528.2 |
+------------+-------------+
```
Cambio de rutinas en comun de los triggers por un SP
```sql
DROP PROCEDURE IF EXISTS sp_triggers;
DELIMITER $$
CREATE PROCEDURE sp_triggers()
BEGIN
DELETE FROM facturacion;
INSERT INTO facturacion
SELECT A.fecha, SUM(B.cantidad * B.precio) AS VENTA_TOTAL
FROM facturas A
INNER JOIN
items B
ON A.numero = B.numero
GROUP BY A.fecha;
END $$
DROP TRIGGER tg_facturacion_insert $$
DROP TRIGGER tg_facturacion_delete $$
DROP TRIGGER tg_facturacion_update $$
CREATE TRIGGER tg_facturacion_insert
AFTER INSERT ON items
FOR EACH ROW BEGIN
CALL sp_triggers;
END $$
CREATE TRIGGER tg_facturacion_delete
AFTER DELETE ON items
FOR EACH ROW BEGIN
CALL sp_triggers;
END $$
CREATE TRIGGER tg_facturacion_update
AFTER UPDATE ON items
FOR EACH ROW BEGIN
CALL sp_triggers;
END $$
DELIMITER ;
```