[
  {
    "path": "01_Reading/00_comments.sql",
    "content": "/*\nCOMENTAROS\nLección 10.1: https://youtu.be/OuJerKzV5T0?t=7512\n*/\n\n-- Comentario en una lína\n\n/*\nEste\nes\nun\ncomentario\nen\nvarias\nlíneas\n*/"
  },
  {
    "path": "01_Reading/01_select.sql",
    "content": "/*\nSELECT\nLección 8: https://youtu.be/OuJerKzV5T0?t=5618\n*/\n\n-- Obtiene todos los datos de la tabla \"users\"\nSELECT * FROM users;\n\n-- Obtiene todos los nombres de la tabla \"users\"\nSELECT name FROM users;\n\n-- Obtiene todos los identificadores y nombres de la tabla \"users\"\nSELECT user_id, name FROM users;"
  },
  {
    "path": "01_Reading/02_distinct.sql",
    "content": "/*\nDISTINCT\nLección 9.1: https://youtu.be/OuJerKzV5T0?t=6089\n*/\n\n-- Obtiene todos los datos distintos entre sí de la tabla \"users\"\nSELECT DISTINCT * FROM users;\n\n-- Obtiene todos los valores distintos referentes al atributo edad de la tabla \"users\"\nSELECT DISTINCT age FROM users;"
  },
  {
    "path": "01_Reading/03_where.sql",
    "content": "/*\nWHERE\nLección 9.2: https://youtu.be/OuJerKzV5T0?t=6384\n*/\n\n-- Filtra todos los datos de la tabla \"users\" con edad igual a 15\nSELECT * FROM users WHERE age = 15;\n\n-- Filtra todos los nombres de la tabla \"users\" con edad igual a 15\nSELECT name FROM users WHERE age = 15;\n\n-- Filtra todos los nombres distintos de la tabla \"users\" con edad igual a 15\nSELECT DISTINCT name FROM users WHERE age = 15;\n\n-- Filtra todas las edades distintas de la tabla \"users\" con edad igual a 15\nSELECT DISTINCT age FROM users WHERE age = 15;"
  },
  {
    "path": "01_Reading/04_order_by.sql",
    "content": "/*\nORDER BY\nLección 9.3: https://youtu.be/OuJerKzV5T0?t=6592\n*/\n\n-- Ordena todos los datos de la tabla \"users\" por edad (ascendente por defecto)\nSELECT * FROM users ORDER BY age;\n\n-- Ordena todos los datos de la tabla \"users\" por edad de manera ascendente\nSELECT * FROM users ORDER BY age ASC;\n\n-- Ordena todos los datos de la tabla \"users\" por edad de manera descendente\nSELECT * FROM users ORDER BY age DESC;\n\n-- Obtiene todos los datos de la tabla \"users\" con email igual a sara@gmail.com y los ordena por edad de manera descendente\nSELECT * FROM users WHERE email='sara@gmail.com' ORDER BY age DESC;\n\n-- Obtiene todos los nombres de la tabla \"users\" con email igual a sara@gmail.com y los ordena por edad de manera descendente\nSELECT name FROM users WHERE email='sara@gmail.com' ORDER BY age DESC;"
  },
  {
    "path": "01_Reading/05_like.sql",
    "content": "/*\nLIKE\nLección 9.4: https://youtu.be/OuJerKzV5T0?t=6894\n*/\n\n-- Obtiene todos datos de la tabla \"users\" que contienen un email con el texto \"gmail.com\" en su parte final\nSELECT * FROM users WHERE email LIKE '%gmail.com';\n\n-- Obtiene todos datos de la tabla \"users\" que contienen un email con el texto \"sara\" en su parte inicial\nSELECT * FROM users WHERE email LIKE 'sara%';\n\n-- Obtiene todos datos de la tabla \"users\" que contienen un email una arroba\nSELECT * FROM users WHERE email LIKE '%@%';"
  },
  {
    "path": "01_Reading/06_and_or_not.sql",
    "content": "/*\nNOT, AND, OR\nLección 9.5: https://youtu.be/OuJerKzV5T0?t=7194\n*/\n\n-- Obtiene todos datos de la tabla \"users\" con email distinto a sara@gmail.com\nSELECT * FROM users WHERE NOT email = 'sara@gmail.com';\n\n-- Obtiene todos datos de la tabla \"users\" con email distinto a sara@gmail.com y edad igual a 15\nSELECT * FROM users WHERE NOT email = 'sara@gmail.com' AND age = 15;\n\n-- Obtiene todos datos de la tabla \"users\" con email distinto a sara@gmail.com o edad igual a 15\nSELECT * FROM users WHERE NOT email = 'sara@gmail.com' OR age = 15;"
  },
  {
    "path": "01_Reading/07_limit.sql",
    "content": "/*\nLIMIT\nLección 9.6: https://youtu.be/OuJerKzV5T0?t=7395\n*/\n\n-- Obtiene las 3 primeras filas de la tabla \"users\"\nSELECT * FROM users LIMIT 3;\n\n-- Obtiene las 2 primeras filas de la tabla \"users\" con email distinto a sara@gmail.com o edad igual a 15\nSELECT * FROM users WHERE NOT email = 'sara@gmail.com' OR age = 15 LIMIT 2;"
  },
  {
    "path": "01_Reading/08_null.sql",
    "content": "/*\nNULL\nLección 10.2: https://youtu.be/OuJerKzV5T0?t=7615\n*/\n\n-- Obtiene todos datos de la tabla \"users\" de la tabla \"users\" con email nulo\nSELECT * FROM users WHERE email IS NULL;\n\n-- Obtiene todos datos de la tabla \"users\" de la tabla \"users\" con email no nulo\nSELECT * FROM users WHERE email IS NOT NULL;\n\n-- Obtiene todos datos de la tabla \"users\" de la tabla \"users\" con email no nulo y edad igual a 15\nSELECT * FROM users WHERE email IS NOT NULL AND age = 15;\n\n/*\nIFNULL\nLección 10.14: https://youtu.be/OuJerKzV5T0?t=10023\n*/\n\n-- Obtiene el nombre, apellido y edad de la tabla \"users\", y si la edad es nula la muestra como 0\nSELECT name, surname, IFNULL(age, 0) AS age FROM users;"
  },
  {
    "path": "01_Reading/09_min_max.sql",
    "content": "/*\nMIN, MAX\nLección 10.3: https://youtu.be/OuJerKzV5T0?t=7834\n*/\n\n-- Obtiene el valor menor del campo edad de la tabla \"users\"\nSelect MIN(age) FROM users;\n\n-- Obtiene el valor mayor del campo edad de la tabla \"users\"\nSelect MAX(age) FROM users;"
  },
  {
    "path": "01_Reading/10_count.sql",
    "content": "/*\nCOUNT\nLección 10.4: https://youtu.be/OuJerKzV5T0?t=8043\n*/\n\n-- Cuenta cuantas filas contiene la tabla \"users\"\nSelect COUNT(*) FROM users;\n\n-- Cuenta cuantas filas contienen un dato no nulo en el campo edad de la tabla \"users\"\nSelect COUNT(age) FROM users;"
  },
  {
    "path": "01_Reading/11_sum.sql",
    "content": "/*\nSUM\nLección 10.5: https://youtu.be/OuJerKzV5T0?t=8128\n*/\n\n-- Suma todos los valores del campo edad de la tabla \"users\"\nSelect SUM(age) FROM users;"
  },
  {
    "path": "01_Reading/12_avg.sql",
    "content": "/*\nAVG\nLección 10.6: https://youtu.be/OuJerKzV5T0?t=8293\n*/\n\n-- Obitne la media de edad de la tabla \"users\"\nSelect AVG(age) FROM users;"
  },
  {
    "path": "01_Reading/13_in.sql",
    "content": "/*\nIN\nLección 10.7: https://youtu.be/OuJerKzV5T0?t=8335\n*/\n\n-- Ordena todos los datos de la tabla \"users\" con nombre igual a brais y sara\nSELECT * FROM users WHERE name IN ('brais', 'sara')"
  },
  {
    "path": "01_Reading/14_between.sql",
    "content": "/*\nBETWEEN\nLección 10.8: https://youtu.be/OuJerKzV5T0?t=8559\n*/\n\n-- Ordena todos los datos de la tabla \"users\" con edad comprendida entre 20 y 30\nSELECT * FROM users WHERE age BETWEEN 20 AND 30"
  },
  {
    "path": "01_Reading/15_alias.sql",
    "content": "/*\nALIAS\nLección 10.9: https://youtu.be/OuJerKzV5T0?t=8667\n*/\n\n-- Establece el alias 'Fecha de inicio en programación' a la columna init_date\nSELECT name, init_date AS 'Fecha de inicio en programación' FROM users WHERE name = 'Brais'\n\n-- Consulta igual que la anterior. Representa la posibilidad de usar comillas dobles para cadenas\nSELECT name, init_date AS \"Fecha de inicio en programación\" FROM users WHERE name = \"Brais\""
  },
  {
    "path": "01_Reading/16_concat.sql",
    "content": "/*\nCONCAT\nLección 10.10: https://youtu.be/OuJerKzV5T0?t=8826\n*/\n\n-- Concatena en una sola columa los campos nombre y apellido\nSELECT CONCAT('Nombre: ', name, ', Apellidos: ', surname) FROM users\n\n-- Concatena en una sola columa los campos nombre y apellido y le establece el alias 'Nombre completo'\nSELECT CONCAT('Nombre: ', name, ', Apellidos: ', surname) AS 'Nombre completo' FROM users"
  },
  {
    "path": "01_Reading/17_group_by.sql",
    "content": "/*\nGROUP BY\nLección 10.11: https://youtu.be/OuJerKzV5T0?t=8960\n*/\n\n-- Agrupa los resultados por edad diferente\nSELECT MAX(age) FROM users GROUP BY age\n\n-- Agrupa los resultados por edad diferente y cuenta cuantos registros existen de cada una\nSELECT COUNT(age), age FROM users GROUP BY age\n\n-- Agrupa los resultados por edad diferente, cuenta cuantos registros existen de cada una y los ordena\nSELECT COUNT(age), age FROM users GROUP BY age ORDER BY age ASC\n\n-- Agrupa los resultados por edad diferente mayor de 15, cuenta cuantos registros existen de cada una y los ordena\nSELECT COUNT(age), age FROM users WHERE age > 15 GROUP BY age ORDER BY age ASC"
  },
  {
    "path": "01_Reading/18_having.sql",
    "content": "/*\nHAVING\nLección 10.12: https://youtu.be/OuJerKzV5T0?t=9265\n*/\n\n-- Cuenta cuantas filas contienen un dato no nulo en el campo edad de la tabla \"users\" mayor que 3\nSELECT COUNT(age) FROM users HAVING COUNT(age) > 3"
  },
  {
    "path": "01_Reading/19_case.sql",
    "content": "/*\nCASE\nLección 10.13: https://youtu.be/OuJerKzV5T0?t=9486\n*/\n\n-- Obtiene todos los datos de la tabla \"users\" y establece condiciones de visualización de cadenas de texto según el valor de la edad \nSELECT *,\nCASE \n\tWHEN age > 18 THEN 'Es mayor de edad'\n    WHEN age = 18 THEN 'Acaba de cumplir la mayoría de edad'\n    ELSE 'Es menor de edad'\nEND AS '¿Es mayor de edad?'\nFROM users;\n\n-- Obtiene todos los datos de la tabla \"users\" y establece condiciones de visualización de valores booleanos según el valor de la edad \nSELECT *,\nCASE \n\tWHEN age > 17 THEN True\n    ELSE False\nEND AS '¿Es mayor de edad?'\nFROM users;"
  },
  {
    "path": "02_Writing/01_insert.sql",
    "content": "/*\nINSERT\nLección 11.1: https://youtu.be/OuJerKzV5T0?t=10370\n*/\n\n-- Inserta un registro con identificador, nombre y apellido en la tabla \"users\"\nINSERT INTO users (user_id, name, surname) VALUES (8, 'María', 'López')\n\n-- Inserta un registro con nombre y apellido en la tabla \"users\"\nINSERT INTO users (name, surname) VALUES ('Paco', 'Pérez')\n\n-- Inserta un registro con identificador no correlativo, nombre y apellido en la tabla \"users\"\nINSERT INTO users (user_id, name, surname) VALUES (11, 'El', 'Merma')"
  },
  {
    "path": "02_Writing/02_update.sql",
    "content": "/*\nUPDATE\nLección 11.2: https://youtu.be/OuJerKzV5T0?t=10621\n*/\n\n-- Estable el valor 21 para la edad del registro de la tabla \"users\" con identificador igual a 11\nUPDATE users SET age = '21' WHERE user_id = 11\n\n-- Estable el valor 20 para la edad del registro de la tabla \"users\" con identificador igual a 11\nUPDATE users SET age = '20' WHERE user_id = 11\n\n-- Estable edad y una fecha para registro de la tabla \"users\" con identificador igual a 11\nUPDATE users SET age = 20, init_date = '2020-10-12' WHERE user_id = 11"
  },
  {
    "path": "02_Writing/03_delete.sql",
    "content": "/*\nDELETE\nLección 11.3: https://youtu.be/OuJerKzV5T0?t=10920\n*/\n\n-- Elimina el registro de la tabla \"users\" con identificador igual a 11\nDELETE FROM users WHERE user_id = 11;"
  },
  {
    "path": "03_Database/01_create_database.sql",
    "content": "/*\nCREATE DATABASE\nLección 12.1: https://youtu.be/OuJerKzV5T0?t=11064\n*/\n\n-- Crea una base de datos llamada \"test\"\nCREATE DATABASE test;"
  },
  {
    "path": "03_Database/02_drop_database.sql",
    "content": "/*\nDROP DATABASE\nLección 12.2: https://youtu.be/OuJerKzV5T0?t=11180\n*/\n\n-- Elimina la base de datos llamada \"test\"\nDROP DATABASE test;"
  },
  {
    "path": "04_Tables/01_create_table.sql",
    "content": "/*\nCREATE TABLE\nLección 13.1: https://youtu.be/OuJerKzV5T0?t=11292\n*/\n\n-- Crea una tabla llamada \"persons\" con nombre de columna (atributos) de tipo int, varchar y date\nCREATE TABLE persons (\n\tid int,\n    name varchar(100),\n    age int,\n    email varchar(50),\n    created date\n);\n\n/*\nCONSTRAINTS: Restricciones\n*/\n\n/*\nNOT NULL\nLección 13.2: https://youtu.be/OuJerKzV5T0?t=11619\n*/\n\n-- NOT NULL: Obliga a que el campo id posea siempre un valor no nulo\nCREATE TABLE persons2 (\n\tid int NOT NULL,\n    name varchar(100) NOT NULL,\n    age int,\n    email varchar(50),\n    created date\n);\n\n/*\nUNIQUE\nLección 13.3: https://youtu.be/OuJerKzV5T0?t=11787\n*/\n\n-- UNIQUE: Obliga a que el campo id posea valores diferentes\nCREATE TABLE persons3 (\n\tid int NOT NULL,\n    name varchar(100) NOT NULL,\n    age int,\n    email varchar(50),\n    created datetime,\n    UNIQUE(id)\n);\n\n/*\nPRIMARY KEY\nLección 13.4: https://youtu.be/OuJerKzV5T0?t=11911\n*/\n\n-- PRIMARY KEY: Establece el campo id como clave primaria para futuras relaciones con otras tablas\nCREATE TABLE persons4 (\n\tid int NOT NULL,\n    name varchar(100) NOT NULL,\n    age int,\n    email varchar(50),\n    created datetime,\n    UNIQUE(id),\n    PRIMARY KEY(id)\n);\n\n/*\nCHECK\nLección 13.5: https://youtu.be/OuJerKzV5T0?t=12121\n*/\n\n-- CHECK: Establece que el campo age sólo podrá contener valores mayores o iguales a 18\nCREATE TABLE persons5 (\n\tid int NOT NULL,\n    name varchar(100) NOT NULL,\n    age int,\n    email varchar(50),\n    created datetime,\n    UNIQUE(id),\n    PRIMARY KEY(id),\n    CHECK(age>=18)\n);\n\n/*\nDEFAULT\nLección 13.6: https://youtu.be/OuJerKzV5T0?t=12243\n*/\n\n-- DEFAULT: Establece un valor por defecto en el campo created correspondiente a la fecha del sistema\nCREATE TABLE persons6 (\n\tid int NOT NULL,\n    name varchar(100) NOT NULL,\n    age int,\n    email varchar(50),\n    created datetime DEFAULT CURRENT_TIMESTAMP(),\n    UNIQUE(id),\n    PRIMARY KEY(id),\n    CHECK(age>=18)\n);\n\n/*\nAUTO INCREMENT\nLección 13.7: https://youtu.be/OuJerKzV5T0?t=12362\n*/\n\n-- AUTO_INCREMENT: Indica que el campo id siempre se va a incrementar en 1 con cada nuevo inserto\nCREATE TABLE persons7 (\n\tid int NOT NULL AUTO_INCREMENT,\n    name varchar(100) NOT NULL,\n    age int,\n    email varchar(50),\n    created datetime DEFAULT CURRENT_TIMESTAMP(),\n    UNIQUE(id),\n    PRIMARY KEY(id),\n    CHECK(age>=18)\n);"
  },
  {
    "path": "04_Tables/02_drop_table.sql",
    "content": "/*\nDROP TABLE\nLección 13.8: https://youtu.be/OuJerKzV5T0?t=12412\n*/\n\n-- Elimina la tabla llamada \"persons8\"\nDROP TABLE persons8;"
  },
  {
    "path": "04_Tables/03_alter_table.sql",
    "content": "/*\nALTER TABLE\nLección 13.9: https://youtu.be/OuJerKzV5T0?t=12461\n*/\n\n/*\nADD\nLección 13.10: https://youtu.be/OuJerKzV5T0?t=12578\n*/\n\n-- ADD: Añade un nuevo atributo surname a la tabla \"persons8\"\nALTER TABLE persons8\nADD surname varchar(150);\n\n/*\nRENAME COLUMN\nLección 13.11: https://youtu.be/OuJerKzV5T0?t=12624\n*/\n\n-- RENAME COLUMN: Renombra el atributo surname a description en la tabla \"persons8\"\nALTER TABLE persons8\nRENAME COLUMN surname TO description;\n\n/*\nMODIFY COLUMN\nLección 13.12: https://youtu.be/OuJerKzV5T0?t=12675\n*/\n\n-- MODIFY COLUMN: Modifica el tipo de dato del atributo description en la tabla \"persons8\"\nALTER TABLE persons8\nMODIFY COLUMN description varchar(250);\n\n/*\nDROP COLUMN\nLección 13.13: https://youtu.be/OuJerKzV5T0?t=12712\n*/\n\n-- DROP COLUMN: Elimina el atributo description en la tabla \"persons8\"\nALTER TABLE persons8\nDROP COLUMN description;"
  },
  {
    "path": "04_Tables/04_relationships.sql",
    "content": "/*\nTIPOS DE RELACIONES\n*/\n\n/*\nRelación 1:1 (uno a uno)\nLección 15.1: https://youtu.be/OuJerKzV5T0?t=13490\nRelación que indica que un registro en la tabla A se relaciona \ncon un sólo registro en la tabla B y viceversa.\n*/\n\n-- El campo user_id de la tabla \"dni\" es clave foránea de la clave primaria user_id de la tabla \"users\"\n-- (Un usuario sólo puede tener un DNI. Un DNI sólo puede estar asociado a un usuario)\nCREATE TABLE dni(\n\tdni_id int AUTO_INCREMENT PRIMARY KEY,\n    dni_number int NOT NULL,\n    user_id int,\n    UNIQUE(dni_id),\n    FOREIGN KEY(user_id) REFERENCES users(user_id)\n);\n\n/*\nRelación 1:N (uno a muchos)\nLección 15.2: https://youtu.be/OuJerKzV5T0?t=13732\nRelación que indica que un registro en la tabla A puede tener varios registros relacionados en la\ntabla B, pero un registro en la tabla B se relaciona con un sólo registro en la tabla A.\n*/\n\nCREATE TABLE companies(\n\tcompany_id int AUTO_INCREMENT PRIMARY KEY,\n    name varchar(100) NOT NULL\n);\nALTER TABLE users\nADD company_id int;\n\n-- El campo company_id de la tabla \"users\" es clave foránea de la clave primaria company_id de la tabla \"companies\"\n-- (Un empleado (usuario) sólo puede tener una empresa, pero una empresa puede tener muchos empleados (usuarios))\nALTER TABLE users \nADD CONSTRAINT fk_companies\nFOREIGN KEY(company_id) REFERENCES companies(company_id)\n\n/*\nRelación N:M (muchos a muchos)\nLección 15.3: https://youtu.be/OuJerKzV5T0?t=14313\nRelación que indica que un un registro en la tabla A puede relacionarse\ncon varios registros en la tabla B y viceversa.\nRequiere una tabla intermedia o de unión para establecer la relación.\n*/\n\nCREATE TABLE languages(\n\tlanguage_id int AUTO_INCREMENT PRIMARY KEY,\n    name varchar(100) NOT NULL\n);\n\n-- El campo user_id y language_id de la tabla intermedia \"users_languages\" es clave foránea de las\n-- claves primarias user_id de la tabla \"users\" y de language_id de la tabla \"languages\"\n-- Un usuario puede conoces muchos lenguajes. Un lenguaje puede ser conocido por muchos usuarios.\nCREATE TABLE users_languages(\n\tusers_language_id int AUTO_INCREMENT PRIMARY KEY,\n    user_id int,\n    language_id int,\n    FOREIGN KEY(user_id) REFERENCES users(user_id),\n    FOREIGN KEY(language_id) REFERENCES languages(language_id),\n    UNIQUE (user_id, language_id)\n);\n\n/*\nRelación de Auto-Referencia\nRelación que indica que un un registro en la tabla A puede \nrelacionarse con otro registro de la tabla A.\n*/\n\n/*\nINSERT y UPDATE para trabajar con JOIN\n*/\n\n/*\n1:1\nLección 16.1: https://youtu.be/OuJerKzV5T0?t=14994\n*/\n\n-- \"dni\" (Relación 1:1)\nINSERT INTO dni (dni_number, user_id) VALUES (11111111, 1);\nINSERT INTO dni (dni_number, user_id) VALUES (22222222, 2);\nINSERT INTO dni (dni_number, user_id) VALUES (33333333, 3);\nINSERT INTO dni (dni_number) VALUES (44444444);\n\n/*\n1:N\nLección 16.2: https://youtu.be/OuJerKzV5T0?t=15203\n*/\n\n-- \"companies\" y \"users\"  (Relación 1:N)\nINSERT INTO companies (name) VALUES ('MoureDev');\nINSERT INTO companies (name) VALUES ('Apple');\nINSERT INTO companies (name) VALUES ('Google');\n\nUPDATE users SET company_id = 1 WHERE user_id = 1;\nUPDATE users SET company_id = 2 WHERE user_id = 3;\nUPDATE users SET company_id = 3 WHERE user_id = 4;\nUPDATE users SET company_id = 1 WHERE user_id = 7;\n\n/*\nN:M\nLección 16.3: https://youtu.be/OuJerKzV5T0?t=15474\n*/\n\n-- \"languages\" y \"users_languages\"  (Relación N:M)\nINSERT INTO languages (name) VALUES ('Swift');\nINSERT INTO languages (name) VALUES ('Kotlin');\nINSERT INTO languages (name) VALUES ('JavaScript');\nINSERT INTO languages (name) VALUES ('Java');\nINSERT INTO languages (name) VALUES ('Python');\nINSERT INTO languages (name) VALUES ('C#');\nINSERT INTO languages (name) VALUES ('COBOL');\n\nINSERT INTO users_languages (user_id, language_id) VALUES (1, 1);\nINSERT INTO users_languages (user_id, language_id) VALUES (1, 2);\nINSERT INTO users_languages (user_id, language_id) VALUES (1, 5);\nINSERT INTO users_languages (user_id, language_id) VALUES (2, 3);\nINSERT INTO users_languages (user_id, language_id) VALUES (2, 5);"
  },
  {
    "path": "05_Join/01_inner_join.sql",
    "content": "/*\nINNER JOIN (JOIN)\nLección 17.1: https://youtu.be/OuJerKzV5T0?t=16101\n*/\n\n-- Realiza un JOIN de manera incorrecta, ya que no existe un campo de relación\nSELECT * FROM users\nINNER JOIN dni;\n\n-- Obtiene los datos de los usuarios que tienen un dni \nSELECT * FROM users\nINNER JOIN dni\nON users.user_id = dni.user_id;\n\n-- Obtiene los datos de los usuarios que tienen un dni (JOIN es lo mismo que INNER JOIN)\nSELECT * FROM users\nJOIN dni\nON users.user_id = dni.user_id;\n\n-- Obtiene el nombre y el dni de los usuarios que tienen un dni y los ordena por edad\nSELECT name, dni_number FROM users\nJOIN dni\nON users.user_id = dni.user_id\nORDER BY age ASC;\n\n-- Obtiene los datos de los usuarios que tienen empresa\nSELECT * FROM users\nJOIN companies\nON users.company_id = companies.company_id;\n\n-- Obtiene los datos de las empresas que tienen usuarios\nSELECT * FROM companies\nJOIN users\nON users.company_id = companies.company_id;\n\n-- Obtiene el nombre de las empresas junto al nombre de sus usuarios\nSELECT companies.name, users.name FROM companies\nJOIN users\nON companies.company_id = users.company_id;\n\n-- Obtiene los nombres de usuarios junto a los lenguajes que conocen\nSELECT users.name, languages.name\nFROM users_languages\nJOIN users ON users_languages.user_id=users.user_id\nJOIN languages ON users_languages.language_id=languages.language_id;\n\n-- Obtiene los nombres de usuarios junto a los lenguajes que conocen (utilizando otro orden de relación entre tablas)\nSELECT users.name, languages.name\nFROM users\nJOIN users_languages ON users.user_id=users_languages.user_id\nJOIN languages ON users_languages.language_id=languages.language_id;"
  },
  {
    "path": "05_Join/02_left_join.sql",
    "content": "/*\nLEFT JOIN\nLección 17.2: https://youtu.be/OuJerKzV5T0?t=17045\n*/\n\n-- Obtiene los datos de todos los usuarios junto a su dni (lo tenga o no)\nSELECT * FROM users\nLEFT JOIN dni\nON users.user_id = dni.user_id;\n\n-- Obtiene el nombre de todos los usuarios junto a su dni (lo tenga o no)\nSELECT name, dni_number FROM users\nLEFT JOIN dni\nON users.user_id = dni.user_id;\n\n-- Obtiene todos los dni junto al nombre de su usuario (lo tenga o no)\nSELECT name, dni_number FROM dni\nLEFT JOIN users\nON users.user_id = dni.user_id;\n\n-- Obtiene el nombre de todos los usuarios junto a sus lenguajes (los tenga o no)\nSELECT users.name, languages.name\nFROM users\nLEFT JOIN users_languages ON users.user_id=users_languages.user_id\nLEFT JOIN languages ON users_languages.language_id=languages.language_id;"
  },
  {
    "path": "05_Join/03_right_join.sql",
    "content": "/*\nRIGHT JOIN\nLección 17.3: https://youtu.be/OuJerKzV5T0?t=17399\n*/\n\n-- Obtiene todos los dni junto a su usuario (lo tenga o no)\nSELECT * FROM users\nRIGHT JOIN dni\nON users.user_id = dni.user_id;\n\n-- Obtiene todos los dni junto al nombre de su usuario (lo tenga o no)\nSELECT name, dni_number FROM users\nRIGHT JOIN dni\nON users.user_id = dni.user_id;\n\n-- Obtiene el nombre de todos los usuarios junto a su dni (lo tenga o no)\nSELECT name, dni_number FROM dni\nRIGHT JOIN users\nON users.user_id = dni.user_id;\n\n-- Obtiene el nombre de todos los lenguajes junto a sus usuarios (los tenga o no)\nSELECT users.name, languages.name\nFROM users\nRIGHT JOIN users_languages ON users.user_id=users_languages.user_id\nRIGHT JOIN languages ON users_languages.language_id=languages.language_id;"
  },
  {
    "path": "05_Join/04_union.sql",
    "content": "/*\nUNION (FULL JOIN)\nLección 17.4: https://youtu.be/OuJerKzV5T0?t=17536\n*/\n\n-- UNION elimina duplicados\n\n-- Obtiene todos los id de usuarios de las tablas dni y usuarios (exista o no relación)\nSELECT users.user_id AS u_user_id, dni.user_id AS d_user_id\nFROM users\nLEFT JOIN dni\nON users.user_id = dni.user_id\nUNION\nSELECT users.user_id AS user_id, dni.user_id AS d_user_id\nFROM users\nRIGHT JOIN dni\nON users.user_id = dni.user_id;\n\n-- Obtiene todos los datos de las tablas dni y usuarios (exista o no relación)\nSELECT *\nFROM users\nLEFT JOIN dni\nON users.user_id = dni.user_id\nUNION\nSELECT *\nFROM users\nRIGHT JOIN dni\nON users.user_id = dni.user_id;\n\n-- UNION ALL mantiene duplicados"
  },
  {
    "path": "06_Advanced/01_index.sql",
    "content": "/*\nINDEX\nLección 18.1: https://youtu.be/OuJerKzV5T0?t=18219\n*/\n\n-- Crea un índice llamado \"idx_name\" en la tabla \"users\" asociado al campo \"name\"\nCREATE INDEX idx_name ON users(name);\n\n-- Crea un índice único llamado \"idx_name\" en la tabla \"users\" asociado al campo \"name\"\nCREATE UNIQUE INDEX idx_name ON users(name);\n\n-- Crea un índice llamado \"idx_name_surname\" en la tabla \"users\" asociado a los campos \"name\" y \"surname\"\nCREATE UNIQUE INDEX idx_name_surname ON users(name, surname);\n\n-- Elimina el índice llamado \"idx_name\"\nDROP INDEX idx_name ON users;"
  },
  {
    "path": "06_Advanced/02_triggers.sql",
    "content": "/*\nTRIGGERS\nLección 18.2: https://youtu.be/OuJerKzV5T0?t=18961\n*/\n\n-- Crea una tabla de historial para usar en el ejemplo\nCREATE TABLE `hello_mysql`.`email_history` (\n`email_history_id` INT NOT NULL AUTO_INCREMENT,\n`user_id` INT NOT NULL,\n`email` VARCHAR(100) NULL,\nPRIMARY KEY (`email_history_id`),\nUNIQUE INDEX `email_history_id_UNIQUE` (`email_history_id` ASC) VISIBLE);\n\n-- Crea un trigger llamado \"tg_email\" que guarda el email previo en la tabla \"email_history\" siempre\n-- que se actualiza el campo \"email\" en la tabla \"users\"\n\n-- DELIMITER es una directiva que sirve para cambiar el delimitador de instrucciones SQL, que por defecto es ;\n-- Se utiliza cuando se define un bloque de código como un procedimiento donde se requieren múltiples \n-- instrucciones SQL terminadas con punto y coma dentro de un mismo bloque.\nDELIMITER //\nCREATE TRIGGER tg_email\nAFTER UPDATE ON users\nFOR EACH ROW\nBEGIN\n\tIF OLD.email <> NEW.email THEN\n\t\tINSERT INTO email_history (user_id, email)\n\t\tVALUES (OLD.user_id, OLD.email);\n\tEND IF;\nEND//\n\n-- Actualiza el campo \"email\" del usuario 1 la tabla \"users\" para probar el trigger\nUPDATE users SET email = 'mouredev@gmail.com' WHERE user_id = 1\n\n-- Elimina el trigger llamado \"tg_email\"\nDROP TRIGGER tg_email;"
  },
  {
    "path": "06_Advanced/03_views.sql",
    "content": "/*\nVIEWS\nLección 18.3: https://youtu.be/OuJerKzV5T0?t=19663\n*/\n\n-- Crea unaa vista llamada \"v_adult_users\" con los nombres y edades de usuarios de la table \"users\"\n-- que tienen una edad igual o mayor a 18 años.\nCREATE VIEW v_adult_users AS\nSELECT name, age\nFROM users\nWHERE age >= 18;\n\nSELECT * FROM v_adult_users;\n\n-- Elimina la vista llamada \"v_adult_users\"\nDROP VIEW v_adult_users;"
  },
  {
    "path": "06_Advanced/04_stored_procedures.sql",
    "content": "/*\nSTORED PROCEDURES\nLección 18.4: https://youtu.be/OuJerKzV5T0?t=20033\n*/\n\n-- Crea un procedimiento almacenado llamado \"p_all_users\" que obtiene todos los datos de \"users\"\nDELIMITER //\nCREATE PROCEDURE p_all_users()\nBEGIN\n\tSELECT * FROM users;\nEND//\n\n-- Invoca al procedimiento almacenado llamado \"p_all_users\"\nCALL p_all_users;\n\n-- Crea un procedimiento almacenado llamado \"p_age_users\" parametrizado para\n-- obtener usuarios con edad variable\nDELIMITER //\nCREATE PROCEDURE p_age_users(IN age_param int)\nBEGIN\n\tSELECT * FROM users WHERE age = age_param;\nEND//\n\n-- Invoca al procedimiento almacenado llamado \"p_age_users\" con un parámetro de valor 30\nCALL p_age_users(30);\n\n-- Elimina el procedimiento almacenado llamado \"p_age_users\"\nDROP PROCEDURE p_age_users;"
  },
  {
    "path": "06_Advanced/05_transactions.sql",
    "content": "/*\nTRANSACTIONS\nLección 18.5: https://youtu.be/OuJerKzV5T0?t=20501\n*/\n\n-- Inicia una nueva transacción. Desde este punto, todas las modificaciones realizadas en la\n-- base de datos son temporales y solo son visibles dentro de esta transacción\nSTART TRANSACTION\n\n-- Finaliza una transacción con éxito. Cuando se ejecuta, todos los cambios realizados en la\n-- base de datos durante la transacción actual se hacen permanentes y visibles\nCOMMIT\n\n-- Deshace las operaciones realizadas en una transacción, revirtiendo la base de datos\n-- al estado en que se encontraba antes de iniciar la transacción\nROLLBACK"
  },
  {
    "path": "06_Advanced/06_connectors.py",
    "content": "# CONNECTORS\n# Lección 19.1: https://youtu.be/OuJerKzV5T0?t=20876\n# Lección 19.2: https://youtu.be/OuJerKzV5T0?t=21149\n\n# Ejemplo de conexión desde Python a una base de datos local\n# Se ejemplifica cómo evitar SQL INJECTION\nimport mysql.connector\n\n\ndef print_user(user):\n\n    config = {\n        \"host\": \"127.0.0.1\",\n        \"port\": \"3306\",\n        \"database\": \"hello_mysql\",\n        \"user\": \"root\",\n        \"password\": \"root1234\"\n    }\n\n    # config = {\n    #     \"host\": \"bpw0hq9h09e7mqicjhtl-mysql.services.clever-cloud.com\",\n    #     \"port\": \"3306\",\n    #     \"database\": \"bpw0hq9h09e7mqicjhtl\",\n    #     \"user\": \"uqzby88erlhvkrty\",\n    #     \"password\": \"oePXiCOHdU1WRV80NPyv\"\n    # }\n\n    connection = mysql.connector.connect(**config)\n    cursor = connection.cursor()\n\n    query = \"SELECT * FROM users WHERE name=%s;\"\n    print(query)\n    cursor.execute(query, (user,))\n    result = cursor.fetchall()\n\n    for row in result:\n        print(row)\n\n    cursor.close()\n    connection.close()\n\n\nprint_user(\"Brais\")\n# print_user(\"'; UPDATE users SET age = '15' WHERE user_id = 1; --\")\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# Hello SQL\n\n[![SQL](https://img.shields.io/badge/MySQL-8.0+-f29221?style=for-the-badge&logo=mysql&logoColor=white&labelColor=101010)](https://mysql.com)\n[![SQL](https://img.shields.io/badge/PostgreSQL-16+-699eca?style=for-the-badge&logo=postgresql&logoColor=white&labelColor=101010)](https://postgresql.org)\n\n## Curso completo para aprender los fundamentos del lenguaje SQL y bases de datos relacionales\n\n![](./Images/header.jpg)\n\n### 7 horas | +80 lecciones | +50 comandos | con código | desde cero | completo | gratis\n\n### Proyecto realizado durante emisiones en directo desde [Twitch](https://twitch.tv/mouredev)\n> ##### Si consideras útil el curso, apóyalo haciendo \"★ Star\" en el repositorio. ¡Gracias!\n\n## Curso completo en vídeo\n\n<a href=\"https://youtu.be/OuJerKzV5T0\"><img src=\"http://i3.ytimg.com/vi/OuJerKzV5T0/maxresdefault.jpg\" style=\"height: 50%; width:50%;\"/></a>\n\n**Este es el curso completo en [vídeo](https://youtu.be/OuJerKzV5T0) de 7 horas en YouTube asociado al código de este repositorio.**\n\n## Lecciones y código\n\n[INTRODUCCIÓN](https://youtu.be/OuJerKzV5T0)\n\n1. [Bases de datos SQL](https://youtu.be/OuJerKzV5T0?t=234)\n2. [Sistema de gestión de base de datos](https://youtu.be/OuJerKzV5T0?t=1011)\n3. [Fundamentos de SQL y bases de datos](https://youtu.be/OuJerKzV5T0?t=1347)\n4. [Configuración e instalación](https://youtu.be/OuJerKzV5T0?t=2753)\n5. [Primeros pasos](https://youtu.be/OuJerKzV5T0?t=3282)\n6. [Conexión y cliente SQL](https://youtu.be/OuJerKzV5T0?t=3555)\n7. [Inicialización de datos](https://youtu.be/OuJerKzV5T0?t=4381)\n8. [Consulta de datos: `SELECT`](https://youtu.be/OuJerKzV5T0?t=5618) ➔ [[Código]](./01_Reading/01_select.sql)\n9. [Modificadores: Parte 1](https://youtu.be/OuJerKzV5T0?t=6074)\n\t1. [`DISTINCT`](https://youtu.be/OuJerKzV5T0?t=6089) ➔ [[Código]](./01_Reading/02_distinct.sql)\n\t2. [`WHERE`](https://youtu.be/OuJerKzV5T0?t=6384) ➔ [[Código]](./01_Reading/03_where.sql)\n\t3. [`ORDER BY`](https://youtu.be/OuJerKzV5T0?t=6592) ➔ [[Código]](./01_Reading/04_order_by.sql)\n\t4. [`LIKE`](https://youtu.be/OuJerKzV5T0?t=6894) ➔ [[Código]](./01_Reading/05_like.sql)\n\t5. [`AND, OR, NOT`](https://youtu.be/OuJerKzV5T0?t=7194) ➔ [[Código]](./01_Reading/06_and_or_not.sql)\n\t6. [`LIMIT`](https://youtu.be/OuJerKzV5T0?t=7395) ➔ [[Código]](./01_Reading/07_limit.sql)\n10. [Modificadores: Parte 2](https://youtu.be/OuJerKzV5T0?t=7503)\n\t1. [`COMMENTS`](https://youtu.be/OuJerKzV5T0?t=7512) ➔ [[Código]](./01_Reading/00_comments.sql)\n\t2. [`NULL`](https://youtu.be/OuJerKzV5T0?t=7615) ➔ [[Código]](./01_Reading/08_null.sql)\n\t3. [`MIN, MAX`](https://youtu.be/OuJerKzV5T0?t=7834) ➔ [[Código]](./01_Reading/09_min_max.sql)\n\t4. [`COUNT`](https://youtu.be/OuJerKzV5T0?t=8043) ➔ [[Código]](./01_Reading/10_count.sql)\n\t5. [`SUM`](https://youtu.be/OuJerKzV5T0?t=8128) ➔ [[Código]](./01_Reading/11_sum.sql)\n\t6. [`AVG`](https://youtu.be/OuJerKzV5T0?t=8293) ➔ [[Código]](./01_Reading/12_avg.sql)\n\t7. [`IN`](https://youtu.be/OuJerKzV5T0?t=8335) ➔ [[Código]](./01_Reading/13_in.sql)\n\t8. [`BETWEEN`](https://youtu.be/OuJerKzV5T0?t=8559) ➔ [[Código]](./01_Reading/14_between.sql)\n\t9. [`ALIAS`](https://youtu.be/OuJerKzV5T0?t=8667) ➔ [[Código]](./01_Reading/15_alias.sql)\n\t10. [`CONCAT`](https://youtu.be/OuJerKzV5T0?t=8826) ➔ [[Código]](./01_Reading/16_concat.sql)\n\t11. [`GROUP BY`](https://youtu.be/OuJerKzV5T0?t=8960) ➔ [[Código]](./01_Reading/17_group_by.sql)\n\t12. [`HAVING`](https://youtu.be/OuJerKzV5T0?t=9265) ➔ [[Código]](./01_Reading/18_having.sql)\n\t13. [`CASE`](https://youtu.be/OuJerKzV5T0?t=9486) ➔ [[Código]](./01_Reading/19_case.sql)\n\t14. [`IFNULL`](https://youtu.be/OuJerKzV5T0?t=10023) ➔ [[Código]](./01_Reading/08_null.sql)\n\t15. [Otros modificadores](https://youtu.be/OuJerKzV5T0?t=10191)\n11. [Escritura de datos](https://youtu.be/OuJerKzV5T0?t=10289)\n\t1. [`INSERT`](https://youtu.be/OuJerKzV5T0?t=10370) ➔ [[Código]](./02_Writing/01_insert.sql)\n\t2. [`UPDATE`](https://youtu.be/OuJerKzV5T0?t=10621) ➔ [[Código]](./02_Writing/02_update.sql)\n\t3. [`DELETE`](https://youtu.be/OuJerKzV5T0?t=10920) ➔ [[Código]](./02_Writing/03_delete.sql)\n12. [Administración de la base de datos](https://youtu.be/OuJerKzV5T0?t=11021)\n\t1. [`CREATE DATABASE`](https://youtu.be/OuJerKzV5T0?t=11064) ➔ [[Código]](./03_Database/01_create_database.sql)\n\t2. [`DROP DATABASE`](https://youtu.be/OuJerKzV5T0?t=11180) ➔ [[Código]](./03_Database/02_drop_database.sql)\n13. [Administración de tablas](https://youtu.be/OuJerKzV5T0?t=11021)\n\t1. [`CREATE TABLE`](https://youtu.be/OuJerKzV5T0?t=11292) ➔ [[Código]](./04_Tables/01_create_table.sql)\n\t2. [`NOT NULL`](https://youtu.be/OuJerKzV5T0?t=11619) ➔ [[Código]](./04_Tables/01_create_table.sql)\n\t3. [`UNIQUE`](https://youtu.be/OuJerKzV5T0?t=11787) ➔ [[Código]](./04_Tables/01_create_table.sql)\n\t4. [`PRIMARY KEY`](https://youtu.be/OuJerKzV5T0?t=11911) ➔ [[Código]](./04_Tables/01_create_table.sql)\n\t5. [`CHECK`](https://youtu.be/OuJerKzV5T0?t=12121) ➔ [[Código]](./04_Tables/01_create_table.sql)\n\t6. [`DEFAULT`](https://youtu.be/OuJerKzV5T0?t=12243) ➔ [[Código]](./04_Tables/01_create_table.sql)\n\t7. [`AUTO INCREMENT`](https://youtu.be/OuJerKzV5T0?t=12362) ➔ [[Código]](./04_Tables/01_create_table.sql)\n\t8. [`DROP TABLE`](https://youtu.be/OuJerKzV5T0?t=12412) ➔ [[Código]](./04_Tables/02_drop_table.sql)\n\t9. [`ALTER TABLE`](https://youtu.be/OuJerKzV5T0?t=12461) ➔ [[Código]](./04_Tables/03_alter_table.sql)\n\t10. [`ADD`](https://youtu.be/OuJerKzV5T0?t=12578) ➔ [[Código]](./04_Tables/03_alter_table.sql)\n\t11. [`RENAME COLUMN`](https://youtu.be/OuJerKzV5T0?t=12624) ➔ [[Código]](./04_Tables/03_alter_table.sql)\n\t12. [`MODIFY COLUMN`](https://youtu.be/OuJerKzV5T0?t=12675) ➔ [[Código]](./04_Tables/03_alter_table.sql)\n\t13. [`DROP COLUMN`](https://youtu.be/OuJerKzV5T0?t=12712) ➔ [[Código]](./04_Tables/03_alter_table.sql)\n14. [Relaciones entre tablas](https://youtu.be/OuJerKzV5T0?t=12781)\n\t1. [RELACIÓN `1:1`](https://youtu.be/OuJerKzV5T0?t=12852)\n\t2. [RELACIÓN `1:N`](https://youtu.be/OuJerKzV5T0?t=13117)\n\t3. [RELACIÓN `N:M`](https://youtu.be/OuJerKzV5T0?t=13208)\n\t4. [AUTOREFERENCIA](https://youtu.be/OuJerKzV5T0?t=13343)\n15. [Creación de tablas relacionadas](https://youtu.be/OuJerKzV5T0?t=13428)\n\t1. [TABLAS `1:1`](https://youtu.be/OuJerKzV5T0?t=13490) ➔ [[Código]](./04_Tables/04_relationships.sql)\n\t2. [TABLAS `1:N`](https://youtu.be/OuJerKzV5T0?t=13732) ➔ [[Código]](./04_Tables/04_relationships.sql)\n\t3. [TABLAS `N:M`](https://youtu.be/OuJerKzV5T0?t=14313) ➔ [[Código]](./04_Tables/04_relationships.sql)\n16. [Almacenamiento de datos relacionados](https://youtu.be/OuJerKzV5T0?t=14635)\n\t1. [DATOS `1:1`](https://youtu.be/OuJerKzV5T0?t=14994) ➔ [[Código]](./04_Tables/04_relationships.sql)\n\t2. [DATOS `1:N`](https://youtu.be/OuJerKzV5T0?t=15203) ➔ [[Código]](./04_Tables/04_relationships.sql)\n\t3. [DATOS `N:M`](https://youtu.be/OuJerKzV5T0?t=15474) ➔ [[Código]](./04_Tables/04_relationships.sql)\n17. [Consulta de datos relacionados](https://youtu.be/OuJerKzV5T0?t=16013)\n\t1. [`INNER JOIN`](https://youtu.be/OuJerKzV5T0?t=16101) ➔ [[Código]](./05_Join/01_inner_join.sql)\n\t2. [`LEFT JOIN`](https://youtu.be/OuJerKzV5T0?t=17045) ➔ [[Código]](./05_Join/02_left_join.sql)\n\t3. [`RIGHT JOIN`](https://youtu.be/OuJerKzV5T0?t=17399) ➔ [[Código]](./05_Join/03_right_join.sql)\n\t4. [`UNION`](https://youtu.be/OuJerKzV5T0?t=17536) ➔ [[Código]](./05_Join/04_union.sql)\n18. [Conceptos avanzados](https://youtu.be/OuJerKzV5T0?t=18196)\n\t1. [`INDEX`](https://youtu.be/OuJerKzV5T0?t=18219) ➔ [[Código]](./06_Advanced/01_index.sql)\n\t2. [`TRIGGER`](https://youtu.be/OuJerKzV5T0?t=18961) ➔ [[Código]](./06_Advanced/02_triggers.sql)\n\t3. [`VIEW`](https://youtu.be/OuJerKzV5T0?t=19663) ➔ [[Código]](./06_Advanced/03_views.sql)\n\t4. [`STORED PROCEDURE`](https://youtu.be/OuJerKzV5T0?t=20033) ➔ [[Código]](./06_Advanced/04_stored_procedures.sql)\n\t5. [TRANSACCIONES](https://youtu.be/OuJerKzV5T0?t=20501) ➔ [[Código]](./06_Advanced/05_transactions.sql)\n\t6. [CONCURRENCIA](https://youtu.be/OuJerKzV5T0?t=20701)\n19. [Conexión desde código](https://youtu.be/OuJerKzV5T0?t=20847)\n\t1. [CONECTORES](https://youtu.be/OuJerKzV5T0?t=20876) ➔ [[Código]](./06_Advanced/06_connectors.py)\n\t2. [SQL INJECTION](https://youtu.be/OuJerKzV5T0?t=21149) ➔ [[Código]](./06_Advanced/06_connectors.py)\n20. [Otros clientes SQL](https://youtu.be/OuJerKzV5T0?t=21641)\n21. [PostgresSQL](https://youtu.be/OuJerKzV5T0?t=22070)\n22. [Despliegue en la nube](https://youtu.be/OuJerKzV5T0?t=23214)\n23. [Próximos pasos](https://youtu.be/OuJerKzV5T0?t=24283)\n\n[CONCLUSIONES](https://youtu.be/OuJerKzV5T0?t=24678)\n\nDurante el curso aprenderemos los fundamentos del lenguaje SQL y las bases de datos relacionales con ejemplos prácticos.\nNos centraremos en MySQL para llevar a cabo las clases, ya que es uno de los más usados en enseñanza y a nivel profesional. También utilizaremos PostgreSQL, por ser una de las bases de datos más populares de la actualidad. De todas formas, no debe preocuparte el motor de bases de datos utilizado, ya que SQL es un lenguaje estándar, por lo que se utilizará prácticamente igual en todas ellas. Una vez lo conozcas no tendrá dificultad alguna llevar esos conocimientos a otros sistemas.  \n\nTodo el código creado durante el curso está disponible para que puedas consultarlo junto a su explicación.\n\n> En el servidor de la comunidad de [Discord](https://discord.gg/mouredev) dispones de un canal llamado \"💾bases-de-datos\" para que puedas comentar lo que quieras.\n\n## Enlaces de interés\n\n* [Documentación SQL](https://www.w3schools.com/sql/default.asp)\n* [MySQL](https://mysql.com)\n* [Descarga MySQL](https://dev.mysql.com/downloads/mysql/)\n* [CLI MySQL](https://dev.mysql.com/doc/refman/8.0/en/mysql.html)\n* [MySQL Workbench](https://dev.mysql.com/downloads/workbench)\n* [PostgreSQL](https://www.postgresql.org)\n* [Clever Cloud](https://www.clever-cloud.com)\n\n## Únete al campus de programación de la comunidad\n\n![https://mouredev.pro](./Images/pro.jpg)\n\n#### Te presento [mouredev pro](https://mouredev.pro), mi proyecto más importante para ayudarte a estudiar programación y desarrollo de software de manera diferente.\n\n> **¿Buscas un extra?** Aquí encontrarás mis cursos editados por lecciones individuales, para avanzar a tu ritmo y guardar el progreso. También dispondrás de ejercicios y correcciones, test para validar tus conocimientos, examen y certificado público de finalización, soporte, foro de estudiantes, reunionnes grupales, cursos exclusivos y mucho más.\n> \n> Entra en **[mouredev.pro](https://mouredev.pro)** y utiliza el cupón **\"PRO\"** con un 10% de descuento en tu primera suscripción.\n\n## ![https://mouredev.com](https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_emote.png) Hola, mi nombre es Brais Moure.\n### Freelance full-stack iOS & Android engineer\n\n[![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCxPD7bsocoAMq8Dj18kmGyQ?style=social)](https://youtube.com/mouredevapps?sub_confirmation=1)\n[![Twitch Status](https://img.shields.io/twitch/status/mouredev?style=social)](https://twitch.com/mouredev)\n[![Discord](https://img.shields.io/discord/729672926432985098?style=social&label=Discord&logo=discord)](https://mouredev.com/discord)\n[![Twitter Follow](https://img.shields.io/twitter/follow/mouredev?style=social)](https://twitter.com/mouredev)\n![GitHub Followers](https://img.shields.io/github/followers/mouredev?style=social)\n![GitHub Followers](https://img.shields.io/github/stars/mouredev?style=social)\n\nSoy ingeniero de software desde 2010. Desde 2018 combino mi trabajo desarrollando Apps con la creación de contenido formativo sobre programación y tecnología en diferentes redes sociales como **[@mouredev](https://moure.dev)**.\n\nSi quieres unirte a nuestra comunidad de desarrollo, aprender programación, mejorar tus habilidades y ayudar a la continuidad del proyecto, puedes encontrarnos en:\n\n[![Twitch](https://img.shields.io/badge/Twitch-Programación_en_directo-9146FF?style=for-the-badge&logo=twitch&logoColor=white&labelColor=101010)](https://twitch.tv/mouredev)\n[![Discord](https://img.shields.io/badge/Discord-Servidor_de_la_comunidad-5865F2?style=for-the-badge&logo=discord&logoColor=white&labelColor=101010)](https://mouredev.com/discord) [![Pro](https://img.shields.io/badge/Cursos-mouredev.pro-FF5500?style=for-the-badge&logo=gnometerminal&logoColor=white&labelColor=101010)](https://moure.dev)\n[![Link](https://img.shields.io/badge/Links_de_interés-moure.dev-14a1f0?style=for-the-badge&logo=Linktree&logoColor=white&labelColor=101010)](https://moure.dev) [![Web](https://img.shields.io/badge/GitHub-MoureDev-087ec4?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/mouredev)\n"
  }
]