mysql (de superficial a profundo)

1. Clasificación de bases de datos y clasificación SQL.

  • Las bases de datos se dividen principalmente en dos categorías: 关系型数据库y 非关系型数据库;

  • Base de datos relacional: MySQL, Oracle, DB2, SQL Server, Postgre SQL, etc.;

    • Las bases de datos relacionales generalmente las creamos nosotros 很多个二维数据表;
    • Las tablas de datos están relacionadas entre sí para formar 一对一、一对多、多对多relaciones iguales.
    • Luego podemos utilizar SQL语句los 多张表中查询datos que necesitamos;
  • Base de datos no relacional: MongoDB, Redis, Memcached, HBse , etc.;

    • El nombre en inglés de la base de datos no relacional en realidad no es solo SQL, también conocido como NoSQL;
    • Hablando claramente 非关系型数据库比较简单一些,存储数据也会更加自由(incluso podemos insertar un objeto json complejo directamente en la base de datos);
  • NoSQL se basa en Key-Valuela relación correspondiente y no es necesario pasarlo durante el proceso de consulta SQL解析;

Clasificación de sentencias SQL

  • DDL(Lenguaje de definición de datos): lenguaje de definición de datos;
    • Puede utilizar declaraciones DDL para realizar operaciones en bases de datos o tablas: crear, eliminar, modificar, etc.;
  • DML(Lenguaje de manipulación de datos): Lenguaje de manipulación de datos;
    • Los campos de la tabla se pueden agregar, eliminar, modificar, etc. mediante declaraciones DML ;
  • DQL(Lenguaje de consulta de datos): lenguaje de consulta de datos;
    • Los registros se pueden consultar desde la base de datos a través de DQL; (énfasis)
  • DCL(Lenguaje de control de datos): Lenguaje de control de datos;
    • Realizar operaciones de control de acceso relacionadas con permisos de tablas y bases de datos;

2. Tipos de datos SQL

  • Los tipos de datos soportados por MySQL son: 数字类型,日期和时间类型,字符串(字符和字节)类型,空间类型和 JSON数据类型.

  • tipo numérico

    • Tipos numéricos enteros: INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT;
    • Tipo de número de punto flotante: FLOAT, DOUBLE (FLOAT es de 4 bytes, DOUBLE es de 8 bytes)
    • Tipos numéricos exactos: DECIMAL, NUMERIC (DECIMAL es la forma de implementación de NUMERIC);
    • Número de bytes ocupados por tipo de entero
  • Tipo de fecha :

    • YEARMostrar valor en formato AAAA
      • Rango 1901 a 2155 y 0000.
    • DATEEl tipo se utiliza para valores con una parte de fecha pero sin parte de hora:
      • FECHA muestra valores en el formato AAAA-MM-DD;
      • El rango admitido es '1000-01-01' a '9999-12-31';
    • DATETIMEEscriba valores que contengan partes de fecha y hora:
      • DATETIME muestra el valor en el formato 'AAAA-MM-DD hh:mm:ss';
      • El rango admitido es 1000-01-01 00:00:00 a 9999-12-31 23:59:59
    • TIMESTAMPLos tipos de datos se utilizan para valores que contienen componentes de fecha y hora:
      • TIMESTAMP muestra valores en el formato 'AAAA-MM-DD hh:mm:ss';
      • Pero su rango es el rango de tiempo UTC: '1970-01-01 00:00:01' a '2038-01-19 03:14:07'
    • Los valores DATETIME o TIMESTAMP pueden incluir fracciones de segundo con una precisión de hasta microsegundos (6 dígitos)
      • Por ejemplo, el rango representado por DATETIME puede ser '1000-01-01 00:00:00.000000' a '9999-12-31 23:59:59.999999'
  • tipo de cadena

    • CHAREl tipo tiene una longitud fija al crear la tabla y la longitud puede tener cualquier valor entre 0 y 255;
      • Cuando se realice una consulta, se eliminarán los siguientes espacios;
    • VARCHAREl valor del tipo es 可变长度una cadena y la longitud se puede especificar como un valor entre 0 y 65535;
      • Al ser consultado no se eliminarán los siguientes espacios;
  • tipo BLOB

    • Se utiliza para almacenar tipos binarios grandes;
  • Tipo de texto

    • Se utiliza para almacenar tipos de cadenas grandes;

3. DDL CRUD

3.1 Operación de la biblioteca

  • Ver todas las bases de datos
 SHOW DATABASES
  • usar una base de datos
USE 数据库
  • Ver la base de datos actualmente en uso
 SELECT DATABASE()
  • Crear base de datos
CREATE DATABASE IF NOT EXISTS 数据库名称
  • Eliminar base de datos
DROP DATABASE IF EXIT 数据库名称
  • Modificar el juego de caracteres y la intercalación de la base de datos.
ALTER DATABASE bilibili CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;

3.2 Restricciones de la tabla

  • restricciones de clave primariaPRIMARY KEY

    • En una tabla, para distinguir la unicidad de cada registro , debe haber un campo que nunca se repetirá y no estará vacío, este campo es la clave principal:
      • La clave principal es el único índice de la tabla ;
      • y debe ser NOT NULL, si no está configurado NOT NULL, entoncesMySQL也会隐式的设置为NOT NULL
      • La clave principal también puede ser un índice de varias columnas, PRIMARY KEY(key_part, ...)que generalmente llamamos clave primaria conjunta;
  • solo:UNIQUE

    • Los campos que utilizan UNIQUErestricciones deben ser diferentes en la tabla y no repetidos
    • UNIQUE Los índices permiten que las columnas que contienen NULL tengan múltiples valores NULL;
  • No puede estar vacío:NOT NULL

    • Para algunos campos, requerimos que los usuarios inserten valores y no pueden estar vacíos. En este caso, podemos usar NOT NULL para restringir;
  • valor por defecto:DEFAULT

    • Para algunos campos, queremos dar un valor predeterminado cuando no se establece ningún valor. En este caso, podemos usar DEFAULT para completar
  • Autoincremento:AUTO_INCREMENT

    • Esperamos que algunos campos se puedan incrementar sin establecer un valor, como el del usuario id. En este caso, se puede usar AUTO_INCREMENT para completar
  • restricciones de clave externaFOREIGN KEY(外键id) REFERENCES brand(被引用的id)
    Insertar descripción de la imagen aquí

3.3 Operaciones de mesa

  • Ver todas las hojas de datos
SHOW TABLES;
  • Ver una estructura de tabla
DESC user;
  • Crear tabla de datos
CREATE TABLE IF NOT EXISTS `user`(
  name  VARCHAR(10),
	age INT,
	height DOUBLE
);
  • Eliminar tabla
DROP TABLE IF EXISTS `user`
  • Modificar el nombre de la tabla
ALTER TABLE `user` RENAME TO `t_user` 
  • Optimizar la tabla de usuarios creada.
CREATE TABLE IF NOT EXISTS `user`(
   id INT PRIMARY KEY AUTO_INCREMENT,
   name VARCHAR(20) UNIQUE NOT NULL,
   sex INT DEFAULT(0),
   tel VARCHAR(20)
);
  • Operaciones de campo de tabla
# 1.添加一个新的列
ALTER TABLE `user` ADD `publishTime` DATETIME;
# 2.删除一列数据
ALTER TABLE `user` DROP `updateTime`;
# 3.修改列的名称
ALTER TABLE `user` CHANGE `publishTime` `publishDate` DATE;
# 4.修改列的数据类型
ALTER TABLE `user` MODIFY `id` INT

4 DML CRUDO

  • Crear nuevas tablas e implementar CURD básico
CREATE TABLE IF NOT EXISTS `t_products`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	title VARCHAR(20) UNIQUE NOT NULL,
	description VARCHAR(200) DEFAULT '',
	price DOUBLE DEFAULT 0,
	publishTime DATETIME
);


-- 插入表数据
INSERT INTO `t_products` (title,description, price,publishTime) VALUES('huawei1000','描述华为',8000.0,'2012-11-9')
INSERT INTO `t_products` (title, description, price, publishTime) VALUES ('华为666', '华为666只要6666', 6666, '2166-06-06');
INSERT INTO `t_products` (title, description, price, publishTime) VALUES ('xiaomi666', 'xiaomi666只要6666', 6666, '2116-06-06');


-- 删除数据
-- 1. 删除表里面的所有数据
DELETE FROM `t_products`
-- 2. 根据条件来(id)删除语句
DELETE FROM `t_products` WHERE id=2 
-- 修改数据表
-- 1. 修改表里面的所有数据
UPDATE `t_products` SET price=888;

-- 2.根据条件修改表里的数据
UPDATE `t_products` SET price=888 WHERE id=5;

-- 3.根据条件修改多个数据
UPDATE `t_products` SET price=999,description='xiaomi666只要999' WHERE id=5

-- 修改数据显示最新的更新时间,并把更新的时间也做一个记录
-- TIMESTAMP数据类型被用于同时包含日期和时间部分的值:
-- CURRENT_TIMESTAMP 记录当前的时间

ALTER TABLE `t_products` ADD `updataTime`
   TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 

5. DQL (lenguaje de consulta de datos)

  • SELECT se utiliza para recuperar filas seleccionadas (Registro) de una o más tablas.
  • El formato de consulta es el siguiente.
    Insertar descripción de la imagen aquí

5.1 Consulta de tabla única

CREATE TABLE IF NOT EXISTS `products` (
	id INT PRIMARY KEY AUTO_INCREMENT,
	brand VARCHAR(20),
	title VARCHAR(100) NOT NULL,
	price DOUBLE NOT NULL,
	score DECIMAL(2,1),
	voteCnt INT,
	url VARCHAR(100),
	pid INT
);

--  查询
-- 1.查询所有
SELECT * FROM `products`

--  2. 查询指定的字段 price title 	brand
SELECT price, title,brand FROM `products`
-- 3 别名查询 as  ,同时as关键字也是可以省略...
SELECT price as productsPrice, title productsTitle,brand FROM `products`

-- 条件查询-比较运算符
SELECT*FROM `products` WHERE price<1000 

SELECT*FROM `products` WHERE price=939

SELECT*FROM `products` WHERE brand='小米' 


-- 查询条件,逻辑运算符
-- 1. and 关键字与 && 一样
SELECT*FROM `products` WHERE brand='小米' AND price=939
-- 2. 逻辑或 or 
SELECT*FROM `products` WHERE brand='华为' || price>=8000

-- 区间范围查询
-- 1. 关键字 BETWEEN AND
SELECT*FROM `products` WHERE price>=1000 && price<=2000
SELECT*FROM `products`WHERE price BETWEEN 1000 AND 2000

-- 枚举出多个结果,其中之一 
SELECT*FROM `products` WHERE brand='小米' OR brand='华为'

SELECT*FROM `products` WHERE brand IN('小米','华为')


-- 模糊查询link 与特殊符号 % 与 
-- 1. 查询title以v开头
SELECT * FROM `products` WHERE title LIKE 'v%';

-- 2.查询带M的title
SELECT * FROM `products` WHERE title LIKE '%M%';
-- 3.查询带M的title必须是第三个字符 (前面字符利用  _ )既下划线
SELECT * FROM `products` WHERE title LIKE '__M%';


-- 排序 ORDER BY 
--  DESC:降序排列;
--    ASC:升序排列;
-- 1.价格小于1000 降序
 SELECT * FROM `products` WHERE price < 1000 ORDER BY price ASC
 
 -- 分页查询 用法[LIMIT {[offset,] row_count | row_count OFFSET offset}]
--  1.limit 限制20条数据
 SELECT * FROM `products` LIMIT 20
 
--  2. OFFSET 偏移数据 (重第41条数据开始查询,查询20条)
 SELECT * FROM `products` LIMIT 20 OFFSET 40
--  另外一种写法:offset, row_count
SELECT * FROM `products` LIMIT 40, 20

5.2 Consulta de agregación y consulta de grupo

  • En la consulta de grupo, si Group Byse agregan algunas restricciones a los resultados de la consulta, podemos usar: HAVING.
-- 1. 计算华为手机的平均价格
SELECT AVG(price) FROM `products` WHERE  brand='华为'
-- 2.所有手机的平均分数
SELECT AVG(score) FROM `products`

-- 3.手机中最低和最高分数
SELECT MAX(score) FROM `products`;
SELECT MIN(score) FROM `products`;
-- 4.计算总投票人数
SELECT SUM(voteCnt) FROM `products`;
--  5.计算 华为手机的个数
SELECT COUNT(*) FROM `products` WHERE brand = '华为'

-- 6. 分组 GROUP BY  
--  6.1 对品牌进行分组
SELECT brand FROM `products` GROUP BY brand
-- 6.2 分组后查看最低和最高的手机价格 
-- ROUND 保留的小数ROUND(AVG(price),2)
SELECT brand,MAX(price),MIN(price) FROM `products` GROUP BY brand
-- 6.3 分组查询后进行价格最大值的约束 HAVING
SELECT brand,MAX(price) AS priceMAX,MIN(price) AS priceMin FROM `products` GROUP BY brand HAVING priceMAX > 4000

5.3 Consultas de varias tablas y restricciones de clave externa

  • Actualizar y eliminar el análisis de datos cuando exista una clave externa
    • RESTRICT(Restricción): al eliminar el registro correspondiente en la tabla principal (es decir, la tabla fuente de la clave externa), primero verifique si el registro tiene una clave externa correspondiente y, de ser así, no se permite la eliminación.
    • NO ACTION: Consistente con RESTRICT, es decir, si existen datos esclavos, no se permite eliminar los datos maestros.
    • CASCADE: Cuando se actualiza o elimina un registro, se comprobará si el registro tiene un registro de clave externa asociado.
      • Actualización: Luego se actualizará el registro correspondiente;
      • Eliminar: Luego los registros asociados se eliminarán juntos;
    • SET NULL: Cuando se actualiza o elimina un registro, se comprobará si el registro tiene un registro de clave externa asociado, de ser así, el valor correspondiente se establecerá en NULL.
-- 多张表的查询
CREATE TABLE IF NOT EXISTS `t_song`(
  id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(20) NOT NULL,
	duration INT DEFAULT 0,
	singer VARCHAR(10)
-- 	外键约束 这里的意思是singer_id 是外键约束 约束需要引入brand这个表里面的id
--   singer_id INT,
-- 	FOREIGN KEY(singer_id) REFERENCES brand(id)
);

INSERT INTO `t_song` (name,duration,singer) VALUES('爸爸妈妈',100,'李荣浩') 
INSERT INTO `t_song` (name,duration,singer) VALUES('戒烟',120,'李荣浩') 
INSERT INTO `t_song` (name,duration,singer) VALUES('从前的那个少年',100,'李荣浩') 

-- 2.创建歌手表
CREATE TABLE IF NOT EXISTS `t_singer`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(10),
	intro VARCHAR(200)
)
-- 插入数据
INSERT INTO `t_singer` (name, intro) VALUES ('五月天', '五月天,全亚洲代表性摇滚乐团。演出足迹踏遍美国,澳洲以及全亚洲地区.')
INSERT INTO `t_singer` (name, intro) VALUES ('李荣浩', '李荣浩,全亚洲代表歌曲制作。')

-- 3.修改歌曲表
ALTER TABLE `t_song` DROP `singer`;
ALTER TABLE `t_song` ADD `singer_id` INT;


多表查询
-- 4.为了品牌单独创建一张表并插入数据
CREATE TABLE IF NOT EXISTS `brands`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(10) UNIQUE NOT NULL,
	website VARCHAR(100),
	worldRank INT
);
INSERT INTO `brands` (name, website, worldRank) VALUES ('华为', 'www.huawei.com', 1);
INSERT INTO `brands` (name, website, worldRank) VALUES ('小米', 'www.mi.com', 10);
INSERT INTO `brands` (name, website, worldRank) VALUES ('苹果', 'www.apple.com', 5);
INSERT INTO `brands` (name, website, worldRank) VALUES ('oppo', 'www.oppo.com', 15);
INSERT INTO `brands` (name, website, worldRank) VALUES ('京东', 'www.jd.com', 3);
INSERT INTO `brands` (name, website, worldRank) VALUES ('Google', 'www.google.com', 8);

-- 4.1外键约束 
   --  为products表添加brand_id 
ALTER TABLE `products` ADD `brand_id` INT
   -- 为外键添加约束 并引用表brand中的id字段  REFERENCES brand(id)=>引用brands中的id
ALTER TABLE `products` ADD FOREIGN KEY (brand_id) REFERENCES brands(id);
-- 4.2 将products中的brand_id关联到brand中的id的值
UPDATE `products` SET `brand_id` = 1 WHERE `brand` = '华为';
UPDATE `products` SET `brand_id` = 4 WHERE `brand` = 'OPPO';
UPDATE `products` SET `brand_id` = 3 WHERE `brand` = '苹果';
UPDATE `products` SET `brand_id` = 2 WHERE `brand` = '小米';
-- 5. 外键约束的情况下修改
UPDATE `brands` SET id=100 WHERE id=1
--  1451 - Cannot delete or update a parent row: a foreign key constraint fails (`music_db`.`products`, CONSTRAINT `products_ibfk_1` FOREIGN KEY (`brand_id`) REFERENCES `brands` (`id`)) 报错误

-- 6. 查看表中的外键
SHOW CREATE TABLE `products`

-- 7. 删除外键 
ALTER TABLE `products` DROP FOREIGN KEY products_ibfk_1;
-- 8 添加外键,当外键删除或者更新时 引用应该删除或者更新
ALTER TABLE `products` ADD FOREIGN KEY (brand_id) REFERENCES brands(id) 
                     ON UPDATE CASCADE 
                     ON DELETE CASCADE;
UPDATE `brands` SET id=100 WHERE id=1

5.4 Consulta de conexión entre varias tablas

  • Al consultar datos, debido a que los datos existen en varias tablas, las consultas de varias tablas deben combinarse
  • Por ejemplo:
SELECT * FROM `products`, `brand`

Insertar descripción de la imagen aquí

  • En este momento, se consultarán todos los datos de las dos tablas y 648se recuperará un total de datos.
  • Esto combinará cada dato de la primera tabla con cada dato de la segunda tabla;
  • A este resultado lo llamamos 笛卡尔乘积, también lo llamamos 直积, expresado como X*Y;
  • Sin embargo, la mayoría de los resultados de la consulta anterior no tienen sentido y no son lo que necesitamos, por lo que usaremos连接查询

5.4.1 Consulta de enlace izquierdo

  • Si queremos obtener todos los datos de la izquierda (principalmente la tabla de la izquierda)
  • En este momento, significa que no importa si la tabla de la izquierda tiene un valor brand_id correspondiente a la identificación de la tabla de la derecha, se consultarán los datos de la izquierda;
  • El escrito completo es LEFT [OUTER] JOIN, OUTER可以省略pero
    Insertar descripción de la imagen aquí
-- 3.左链接 LEFT [OUTER] JOIN "表" ON 连接条件
-- 这个时候就表示无论左边的表是否有对应的brand_id的值对应右边表的id,左边的数据都会被查询出来;
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id

-- 3.1 查询不为null有交集的数据

SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NOT NULL;

5.4.2 Consulta de unión derecha

- Si queremos obtener todos los datos de la derecha (principalmente la tabla de la derecha) :

  • En este momento, significa que no importa si el brand_id en la tabla de la izquierda corresponde al id en la tabla de la derecha, se consultarán los datos de la derecha;
  • El método de escritura completo es RIGHT [OUTER] JOIN, pero se puede omitir OUTER;
    Insertar descripción de la imagen aquí
SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id=brands.id

5.4.3 Unión interna

  • La combinación interna superior significa que la tabla de la izquierda y la tabla de la derecha tienen asociaciones de datos correspondientes:
    • Puedes escribir CROSS JOINde cualquier manera JOIN;
SELECT * FROM `products` JOIN `brands` ON `products`.brand_id = `brands`.id
  • donde está escrita la conexión interna
SELECT * FROM `products`, `brand` WHERE `products`.brand_id = `brand`.id
  • Comparación de las declaraciones SQL anteriores
  • La unión interna significa que cuando dos tablas están conectadas, la relación entre los datos se verá limitada para determinar los resultados de consultas posteriores.
  • La condición donde significa calcular primero el producto cartesiano y luego seleccionar la condición donde en función de los datos del producto cartesiano.

5.4.4 Conexión completa

  • La unión completa se usa en la especificación SQL FULL JOIN, pero no hay soporte para ella en MySQL. Necesitamos usar UNIONpara lograrlo:
    Insertar descripción de la imagen aquí
(SELECT * FROM `products` LEFT JOIN `brands` ON `products`.brand_id = `brands`.id)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON `products`.brand_id = `brands`.id)
(SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NULL)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id = brands.id WHERE products.id IS NULL)
  • Unirse al resumen de la consulta
--  在查询到产品的同时,显示对应的品牌相关的信息,因为数据是存放在两张表中,所以这个时候就需要进行多表查询

-- //1.  这种默认做法会发生这个表的数据与另一个表的数据会相乘 得到 M*N的数据
SELECT * FROM `products`, `brands`;  
-- 2.过滤查询
SELECT * FROM `products`, `brands` WHERE products.brand_id=brands.id;  
-- 3.左链接 LEFT [OUTER] JOIN "表" ON 连接条件
-- 这个时候就表示无论左边的表是否有对应的brand_id的值对应右边表的id,左边的数据都会被查询出来;
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id

-- 3.1 查询不为null有交集的数据

SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NOT NULL;

-- 4. 右连接 RIGHT [OUTER] JOIN "表" ON 连接条件
-- 这个时候就表示无论左边的表中的brand_id是否有和右边表中的id对应,右边的数据都会被查询出来
SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id=brands.id

-- 5. 内连接 CROSS JOIN或者 JOIN;
-- 5.1内连接效果和下面where查询效果一样的,但是做法确是不一样的
-- 5.1.1SQL语句一:内连接,代表的是在两张表连接时就会约束数据之间的关系,来决定之后查询的结果;
-- 5.1.2SQL语句二:where条件,代表的是先计算出笛卡尔乘积,在笛卡尔乘积的数据基础之上进行where条件的帅选
SELECT * FROM `products` JOIN `brands` ON `products`.brand_id = `brands`.id
SELECT * FROM `products`, `brands` WHERE `products`.brand_id = `brands`.id;

-- 6. 全连接
--  6.1 SQL规范中全连接是使用FULL JOIN,但是MySQL中并没有对它的支持,我们需要使用 UNION 来实现

(SELECT * FROM `products` LEFT JOIN `brands` ON `products`.brand_id = `brands`.id)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON `products`.brand_id = `brands`.id)


(SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NULL)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id = brands.id WHERE products.id IS NULL)

5.5 Consulta de tabla de muchos a muchos

Análisis de muchos a muchos del artículo de referencia

-- 1.多对多关系
-- 1.1. 创建学生表
CREATE TABLE IF NOT EXISTS `students`(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    age INT
);
INSERT INTO `students` (name, age) VALUES('why', 18);
INSERT INTO `students` (name, age) VALUES('tom', 22);
INSERT INTO `students` (name, age) VALUES('lilei', 25);
INSERT INTO `students` (name, age) VALUES('lucy', 16);
INSERT INTO `students` (name, age) VALUES('lily', 20);



-- 1.2. 创建课程表
CREATE TABLE IF NOT EXISTS `courses`(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    price DOUBLE NOT NULL
);

INSERT INTO `courses` (name, price) VALUES ('英语', 100);
INSERT INTO `courses` (name, price) VALUES ('语文', 666);
INSERT INTO `courses` (name, price) VALUES ('数学', 888);
INSERT INTO `courses` (name, price) VALUES ('历史', 80);
INSERT INTO `courses` (name, price) VALUES ('物理', 100);


-- 1.3. 学生选择的课程关系表
CREATE TABLE IF NOT EXISTS `students_select_courses`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	student_id INT NOT NULL,
	course_id INT NOT NULL,
  -- 	外键约束
	FOREIGN KEY (student_id) REFERENCES students(id) ON UPDATE CASCADE ON DELETE CASCADE,
	FOREIGN KEY (course_id) REFERENCES courses(id) ON UPDATE CASCADE ON DELETE CASCADE
);

-- 2 选课情况
-- 2-1 why 选修了 英文和数学
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (1, 1);
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (1, 3);
--  2-2 lilei选修了 语文和数学和历史
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (3, 2);
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (3, 3);
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (3, 4);

-- 3查询数据
--  3.1 所有学生的选课情况(内连接)  students_select_courses(内连接属性)
SELECT * FROM `students` 
JOIN  `students_select_courses` ON students.id= students_select_courses.student_id
JOIN `courses` ON students_select_courses.course_id=courses.id

-- 3.2 别名查询名称
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
JOIN `courses` cou ON students_select_courses.course_id=cou.id

-- 3.3左链接
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
LEFT JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
LEFT JOIN `courses` cou ON students_select_courses.course_id=cou.id

-- 3.4 单个学生选择课程情况 (左连接可以保证,在学生没有选择课的情况也可以显示)
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
LEFT JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
LEFT JOIN `courses` cou ON students_select_courses.course_id=cou.id WHERE stu.id=1

-- 3.5 查询哪些学生没有选择课程
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
LEFT JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
LEFT JOIN `courses` cou ON students_select_courses.course_id=cou.id WHERE cou.id is NULL

-- 3.6查询哪些课程没有被学生选择
SELECT 
stu.name stuName , cou.name couName 
FROM `students` stu
RIGHT JOIN  `students_select_courses` ON stu.id= students_select_courses.student_id
RIGHT JOIN `courses` cou ON students_select_courses.course_id=cou.id WHERE cou.id is NULL

6 Matriz de objetos de consulta

  • Requisito: al realizar consultas de varias tablas, los datos de la Tabla 1 se tratarán como un subconjunto de los datos de la Tabla 2.
  • Requisito 2: al consultar varias tablas, la tabla de información de marca se colocará en un objeto separado y se mostrará en la tabla de productos.
  • Requisito 3: al consultar varias tablas, la información de selección del curso de aprendizaje se colocará en un objeto de matriz.
  • JSON_OBJECT objeto de transferencia
  • JSON_ARRAYAGG和JSON_OBJECTMuchos a muchos para formar
-- 1. 单表查询
SELECT * FROM `products` WHERE price>5000
-- 2. 多表查询
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id
WHERE price>5000

-- 3. 多表查询:品牌信息放到一个单独的对象中
-- 格式 JSON_OBJECT([key, val[, key, val] ...])
SELECT 
products.id as pid,products.title as title,products.price as price,
JSON_OBJECT('id',brands.id,'name',brands.name,'website',brands.website) as brand
FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id
WHERE price>5000

-- 多对多查询
SELECT * FROM `students` as stu
LEFT JOIN `students_select_courses` as ssc ON ssc.student_id=stu.id
LEFT JOIN `courses` as cu ON ssc.course_id =cu.id WHERE cu.id IS NOT NULL

-- 多对多查询分组合并
-- JSON_ARRAYAGG  转为数组对象
SELECT 
stu.id as id, stu.name as name, stu.age as age,
JSON_ARRAYAGG(JSON_OBJECT('id',cs.id,'name',cs.name,'price',cs.price)) as course
FROM `students` as stu
LEFT JOIN `students_select_courses` as ssc ON ssc.student_id=stu.id
LEFT JOIN `courses` as cs ON ssc.course_id =cs.id WHERE cs.id IS NOT NULL
GROUP BY stu.id

Supongo que te gusta

Origin blog.csdn.net/weixin_46104934/article/details/131886318
Recomendado
Clasificación