乐趣区

关于mysql:超详细的mysql总结DQL

上一篇文章总结了 DDL、DML 的应用,这一篇文章把剩下的 DQL 加上~

DQL(Data Query Language)即数据库查询语言,用来查问所须要的信息,在查问的过程中,须要判断所查问的数据与表之间的关系,可能须要的数据在一张表中能够查问到,可能须要联结多张表能力查问到,在这种状况下,查问的语句也不一样。

要进行查问之前,首先须要有表数据,以下 sql 语句创立一张 products 表,存储着不同品牌及型号的手机

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
)

// 省略 insert into 插入数据局部 

首先来查看一下表中的所有数据

SELECT * FROM `products`;

// * 代表展现所有的字段,如果只展现局部字段能够指定,可通过 as 对字段取别名,as 可省略
SELECT id, brand as phoneBrand, title phoneTitle, price, score FROM `products`;

有时候咱们并不需要查问出所有的数据,比方只须要查看所有品牌为华为的手机,这个时候就能够通过 where 来进行解决了

SELECT id, brand as phoneBrand, title phoneTitle, price, score From `products`  WHERE brand = '华为';

// where 后能够跟多个条件,用 AND() 或者 OR 来进行连贯
SELECT * From `products` WHERE brand = '华为' && price > 4000; // 查问价格大于 4000 的华为手机
SELECT * From `products` WHERE score BETWEEN 5 AND 6; // 查问手机评分在 5 - 6 分之间的手机,蕴含 5 和 6 分

SELECT * FROM `products` WHERE brand LIKE '%v%'; // 匹配品牌名称蕴含字母为 V 的数据
SELECT * FROM `products` WHERE brand LIKE '_v%'; // 匹配品牌名称蕴含第二个字母为 V 的数据 

对于获取到的手机数据,价格是随便排列的,不便于咱们查看范畴,想要对数据进行排序,则能够通过 ORDER BY

SELECT id, brand as phoneBrand, title phoneTitle, price, score 
From `products` WHERE brand = '华为' ORDER BY price DESC; 
// DESC 代表降序, ASC 代表升序

// 通过 price 降序排列的时候,雷同价格的产品,再对评分倒序排列
SELECT id, brand as phoneBrand, title phoneTitle, price, score From 
`products` WHERE brand = '华为' ORDER BY price DESC, score DESC;

以上的查问当咱们没有限度查问的数量时,就会把所有符合条件的内容都展现进去,当数据量十分大的时候,就可能存在卡顿的状况,通常状况咱们都会对数据进行分页解决,一次性返回 10 条、20 条,只须要前端告知后端查问的页码和分页的数量即可,应用 LIMIT 来限度数量

SELECT * FROM `products` LIMIT 10 OFFSET 40;

// LIMIT 10 OFFSET 40 代表偏移 40 条数据,往后取 10 条数据
// LIMIT 10, 40 代表偏移 10 条数据,往后取 40 条数据 

以上的查问形式针对于所有的明细数据,如果想要查问某种品牌的平均值,最大值,就须要应用 GROUP BY 来进行分组,应用聚合函数来计算,通过 Having 来限度分组计算后的条件

SELECT brand, AVG(price), MAX(price) as maxPrice, MIN(price) minPrice 
FROM `products` GROUP BY brand;

// 同样能够取别名,不取别名时展现的就是查问语句的字段名称
// 在统计出所有品牌的平均值、最大值、最小值后,取出价格范畴在 1000-5000 之间的
SELECT brand, AVG(price), MAX(price) as maxPrice, MIN(price) minPrice 
FROM `products` GROUP BY brand HAVING maxPrice < 5000 && minPrice > 1000;

// 计算投票总数 SUM(voteCount)
// 计算所有的价格类别,去重 COUNT(DISTINCT price)

以上查问能够总结为以下语句,依据本人数据的须要抉择适合的条件限度

SELECT select_expr [, select_expr]...
    [FROM table_references]
    [WHERE where_condition]
    [ORDER BY expr [ASC | DESC]]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [GROUP BY expr] [HAVING where_condition]

下面都是针对于一张表格来进行查问,但咱们仔细观察,发现表格中的同一品牌手机的 brand 字段都是统一的,如果针对不同的品牌,要减少形容信息、官网等,那么须要在每一条数据中都反复增加,这样表格数据有大量冗余,能够思考另建一张品牌表,搁置品牌数据,这样就只用在商品表中寄存品牌 id,通过外键将商品和品牌关联上。

// 创立商品表
CREATE TABLE IF NOT EXISTS `brand`(
    id INT PRIMARY KEY AUTO_INCREMENT,
    brand VARCHAR(20) NOT NULL,
    phoneRank VARCHAR(20),
    website VARCHAR(100)
);

在 products 表中通过外键 FOREIGN KEY 与 brand 表关联上

ALTER TABLE `products` ADD brand_id INT;
ALTER TABLE `products` ADD FOREIGN KEY(brand_id) REFERENCES brand(id);
UPDATE `products` SET brand_id = 1 WHERE brand = '苹果';
UPDATE `products` SET brand_id = 2 WHERE brand = 'VIVO';
UPDATE `products` SET brand_id = 3 WHERE brand = 'oppo';
UPDATE `products` SET brand_id = 4 WHERE brand = '小米';
UPDATE `products` SET brand_id = 7 WHERE brand = '华为';
SELECT * FROM `products`;

关联外键之后,就能够通过两张表一起查问了,查问形式分为四种,别离是左连贯(LEFT JOIN,以右边的表为主,下图①④),右连贯(RIGHT JOIN,以左边的表为主,下图 ②⑤),内连贯(INNER / CROSS JOIN,左右两张图重叠处,下图③),外连贯(通过左右连贯组合,下图⑥⑦)

以上连贯形式的区别就在于以哪张表为主,为主的表数据将全副选取,再去匹配对应的条件

// // 左连贯,展现所有的商品,无论商品的品牌在不在品牌表中,对应上图 ①
SELECT products.id, products.title, products.price, brand.id, 
brand.brand, brand.phoneRank, brand.website FROM `products` 
LEFT JOIN `brand` ON products.brand_id = brand.id;

// 内连贯,展现所有有 brand_id 的商品,对应上图 ③
SELECT products.id, products.title, products.price, brand.id,
brand.brand, brand.phoneRank, brand.website FROM `products` 
INNER JOIN `brand` ON products.brand_id = brand.id;

// 右连贯,展现所有的品牌,无论是否存在该品牌的商品,对应上图⑤
SELECT products.id, products.title, products.price, brand.id, 
brand.brand, brand.phoneRank, brand.website FROM `products` 
RIGHT JOIN `brand` ON products.brand_id = brand.id 
WHERE products.brand_id IS NULL;

// 外连贯,展现所有商品和所有的品牌,对应上图 ⑥
(SELECT products.id, products.title, products.price, brand.id, brand.brand, 
brand.phoneRank, brand.website FROM `products` LEFT JOIN `brand` 
ON products.brand_id = brand.id)
UNION
(SELECT products.id, products.title, products.price, brand.id, brand.brand, 
brand.phoneRank, brand.website FROM `products` RIGHT JOIN `brand` 
ON products.brand_id = brand.id)

以上是一对多的查问状况,还有多对多的状况,那就更为简单一些,举个例子,学校提供了一些课程供学生自主抉择,他们可任意抉择 2 - 4 门课程,这种状况下必定会存在一个学生表记录所有的学生信息,还有一张课程表,记录所有的课程信息,如何将学生和课程关联起来,在学生表中减少一个字段用来记录选课 id,用逗号分隔吗?这种形式能够,每一次减少数据或者删除数据都须要对所有的数据进行获取,而后还得通过代码来实现,并不是最优解,最好的形式是建设一个关系表,将学生和课程之间的关系全副保留到这张表当中

// 学生表
CREATE TABLE IF NOT EXISTS `students`(
   id INT PRIMARY KEY AUTO_INCREMENT,
   name VARCHAR(20) NOT NULL, age INT
);

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

// 学生选课关系表,设置联结主键,保障学生不会反复选课
CREATE TABLE IF NOT EXISTS `students_select_courses`(
    student_id INT NOT NULL,
    courses_id INT NOT NULL,
    FOREIGN KEY(student_id) REFERENCES students(id) ON UPDATE CASCADE,
    FOREIGN KEY(courses_id) REFERENCES courses(id) ON UPDATE CASCADE,
    PRIMARY KEY(student_id, courses_id)
);

创立三张表,并增加数据后,通过 左连贯、右连贯、内连贯等形式组合在一起查问出所须要的数据

// 左连贯,查问所有的学生选课状况
SELECT * FROM students stu
LEFT JOIN students_select_courses ssc ON stu.id = ssc.student_id
LEFT JOIN courses cour ON cour.id = ssc.courses_id;

// 查问所有选课的学生状况
SELECT stu.name stuName, stu.age, cour.name courseName, 
cour.price courPrice FROM students stu 
LEFT JOIN students_select_courses ssc ON stu.id = ssc.student_id 
LEFT JOIN courses cour ON cour.id = ssc.courses_id
WHERE ssc.courses_id IS NOT NULL;

// 哪些课程没有被抉择
SELECT stu.name stuName, stu.age, cour.name courseName, 
cour.price courPrice FROM students stu
LEFT JOIN students_select_courses ssc ON stu.id = ssc.student_id
RIGHT JOIN courses cour ON cour.id = ssc.courses_id
WHERE stu.id IS NULL;

最初再来看一下如何组装数据,比方在一个字段中形式对象或数组,能够应用 JSON.OBJECT,JSON.ARRAY、JSON.ARRAYAGG

// 组装成对象
SELECT products.id as id, products.title as title,
products.price as price, products.score as score,
JSON_OBJECT('id', brand.id, 'name', brand.brand, 'rank', 
brand.phoneRank, 'website', brand.website) as brand FROM products
LEFT JOIN brand ON products.brand_id = brand.id;

// 数据组装成数组对象
SELECT stu.id, stu.name, stu.age,
JSON_ARRAYAGG(JSON_OBJECT('id', cour.id, 'name', cour.name)) 
as courses FROM students stu
LEFT JOIN students_select_courses ssc ON stu.id = ssc.student_id
RIGHT JOIN courses cour ON cour.id = ssc.courses_id GROUP BY stu.id 
HAVING id IS NOT NULL;

以上就是对于 DQL 的所有内容啦,如果对 DDL、DML 还有不相熟能够参考这一篇~ 超具体的 mysql 总结(基本概念、DDL、DML)

退出移动版