mysql单表去重_MySQL单表查询详细解析
⼀、关键字的执⾏优先级
1,from:找到表
2,where:拿着where指定的约束条件,去⽂件/表中取出⼀条条数据
3,group by:将取出的⼀条条数据进⾏分组,如果没有group by,则整体作为⼀组
4,having:将分组的结果进⾏having过滤
5,lect:执⾏lect
6,distinct:去重
7,order by:将结果按条件排序
8,limit:限制结果的显⽰条数
⼆、去重,四则运算,⾃定义显⽰
#避免重复DISTINCT
SELECT post FROM employee;#直接这样查询我们会看到很多重复的内容,我只想看⼀下有哪些职位,那么多重复的内容是没⽤的,所以我们加⼀个去重的功能,叫做distinct
SELECT DISTINCT post FROM employee; #对查询出来的记录进⾏去重,如果post职位有重复的,就会被剔除,剩下不重复的内容,注意,因为我们查询出来的记录⾥⾯只有⼀个字段post,才会根据post来进⾏去重
SELECT DISTINCT post,salary FROM employee;#但是如果这样写,你会发现,貌似没有起到根据post来去重的效果,因为你的去重条件变成了post和salary两个字段的数据,只有他俩合起来是⼀个重复记录的时候才会去重 #通过四则运算查询
SELECT name, salary*12 FROM employee; #查询每个⼈的年薪,⽉薪我们有记录,查年薪呢?简单的乘以12就可以了,from 库.表的时候,我们已经通过u 库名;来指定了库了,所以from的时候直接写from 表,就⾏了
#你会发现,结果是出来了,但是我们的那个薪资的字段名变成了salary*12,是因为我们通过查询语句查询出来的也是⼀张表,但是这个表是不是内存当中的⼀个虚拟表,并不是我们硬盘中存的那个完整的表,对吧,虚拟表是不是也有标题和记录啊,
既然是⼀个表,我们是可以指定这个虚拟表的标题的,通过as+新字段名来指定
SELECT name, salary*12 AS Annual_salary FROM employee; #as + 新字段名,就是起⼀个别名的意思,上⾯的那个salary*12的字段名也是⼀个别名,只不过不直观,是 mysql ⾃动给你写上的
#除了乘法以外,加减乘除都是可以的
#⾃定义显⽰格式,⾃⼰规定查询结果的显⽰格式
CONCAT() 函数⽤于连接字符串
SELECT CONCAT('姓名: ',name,' 年薪: ', salary*12) AS Annual_salary #我想让name这个字段显⽰的字段名称是中⽂的姓名,让salary*12显⽰的是中⽂的年薪,
FROM employee;#看结果:通过结果你可以看出,这个concat就是帮我们做字符串拼接的,并且拼接之后的结果,都在⼀个叫做
Annual_salary的字段中了
+---------------------------------------+
| Annual_salary |
+---------------------------------------+
| 姓名: egon 年薪: 87603.96 |
| 姓名: alex 年薪: 12000003.72 |
| 姓名: wupeiqi 年薪: 99600.00 |
| 姓名: yuanhao 年薪: 42000.00 |
.....
+---------------------------------------+
SELECT CONCAT('姓名: ',name,' 年薪: ', salary*12) AS Annual_salary,CONCAT('性别:',x) from employee;#还可以这样分成两列
CONCAT_WS() 第⼀个参数为分隔符来进⾏字符串拼接
SELECT CONCAT_WS(':',name,salary*12) AS Annual_salary from employee; #通过冒号来将name和salary连接起来#上⾯这个效果我们也可以通过concat来实现:SELECT CONCAT(name,':',salary*12) AS Annual_salary from employee;
三、where约束
1,⽐较运算符:> < >= <= <> !=
2,between 80 and 100
3,in(80,90,100)
4,like 'ee%' 模糊匹配,%表⽰任意多字符,_表⽰⼀个字符
5,逻辑运算符:在多个条件直接可以⽤逻辑运算符 and or not
#1:单条件查询
SELECT name FROM employee WHERE post='sale'; #注意优先级,我们说where的优先级是不是⽐lect要⾼啊,所以我们的顺序是先找到这个employee表,然后按照post='sale'的条件,然后去表⾥⾯lect数据
#2:多条件查询
SELECT name,salary FROM employee WHERE post='teacher' AND salary>10000;
#3:关键字BETWEEN AND 写的是⼀个区间
SELECT name,salary FROM employee WHERE salary BETWEEN 10000 AND 20000; #就是salary>=10000 and
salary<=20000的数据
SELECT name,salary FROM employee WHERE salary NOT BETWEEN 10000 AND 20000; #加个not,就是不在这个区间内,薪资⼩于10000的或者薪资⼤于20000的,注意没有等于,
#4:关键字IS NULL(判断某个字段是否为NULL不能⽤等号,需要⽤IS) 判断null只能⽤is
SELECT name,post_comment FROM employee WHERE post_comment IS NULL;
SELECT name,post_comment FROM employee WHERE post_comment IS NOT NULL#5:关键字IN集合查询
SELECT name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ; #这样写是不是太⿇烦了,写⼀⼤堆的or,下⾯我们⽤in这个简单的写法来搞
SELECT name,salary FROM employee WHERE salary IN (3000,3500,4000,9000) ;
SELECT name,salary FROM employee WHERE salary NOT IN (3000,3500,4000,9000) ;
#6:关键字LIKE模糊查询,模糊匹配,可以结合通配符来使⽤
通配符’%’ #匹配任意所有字符
SELECT * FROM employee WHERE name LIKE 'eg%';
通配符’_’ #匹配任意⼀个字符
SELECT * FROM employee WHERE name LIKE 'al__'; #注意我这⾥写的两个_,⽤1个的话,匹配不到alex,因为al后⾯还有两个字符ex。
四、分组查询group by
lect * from 表名 group by 字段
对sql_mode进⾏设置为ONLY_FULL_GROUP_BY,此时就会报错,只能查看该字段的内容,但如果没有设定,也只会显⽰每组的第⼀组数据
单独使⽤GROUP BY关键字分组
SELECT post FROM employee GROUP BY post;
注意:我们按照post字段分组,那么lect查询的字段只能是post,想要获取组内的其他相关信息,需要借助函数
GROUP BY关键字和GROUP_CONCAT()函数⼀起使⽤,⽐如说我想按部门分组,每个组有哪些员⼯,都显⽰出来,怎么搞
SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post;#按照岗位分组,并查看组内所有成员名,通过逗号拼接在⼀起
SELECT post,GROUP_CONCAT(name,':',salary) as emp_members FROM employee GROUP BY post;
GROUP BY⼀般都会与聚合函数⼀起使⽤,聚合是什么意思:聚合就是将分组的数据聚集到⼀起,合并起来搞事情,拿到⼀个最后的结果
lect post,count(id) as count from employee group by post;#按照岗位分组,并查看每个组有多少⼈,每个⼈都有唯⼀的id号,我count是计算⼀下分组之后每组有多少的id记录,通过这个id记录我就知道每个组有多少⼈了
关于集合函数,mysql提供了以下⼏种聚合函数:count、max、min、avg、sum等,上⾯的group_concat也算是⼀个聚合函数了,做字符串拼接的操作
五、过滤having
执⾏优先级:where,group by,having
where发⽣在group之前,因⽽where可以⽤任意字段,但绝不能⽤聚合函数
having发⽣在group by之后,因⽽可以⽤分组的字段,⽆法直接⽤到其他字段,having是可以⽤聚合函数的
lect post,avg(salary) from t1 where age > 30 group by post having avg(salary) >10000;
这是得到各部门年龄⼤于30的员⼯的平均⼯资,最后保留平均⼯资⼤于10000的部门
六、查询排序order by
lect * from t1 order by salary #默认升序排列
lect * from t1 order by salary asc; #升序排列
lect * from t1 order by salary desc; #降序排列
lect * from t1 order by age asc,salary desc; #先以年龄升序排列,若年龄相同的就以⼯资降序排列
七、限制查询的记录数limit
lect * from t1 order by salary limit 3; #默认起始位为0,即从第⼀条数据开始,总共显⽰3条数据
lect * from t1 order by salary desc limit 0,5; #起始位为0,即从第⼀条开始,总共显⽰5条数据
lect * from t1 order by salary asc limit 2,6; #起始位为2,即从第三条开始,总共显⽰6条数据
⼋、使⽤正则表达式查询
之前⽤的like是模糊匹配,只有%和_,具有局限性,查询的时候其实可以⽤我们之前学正则
lect * from t1 where name regexp '^ale'; #匹配以ale开头的
lect * from t1 where name regexp 'ss$'; #匹配以ss结尾的lect * from t1 where name regexp 'm{2}' #匹配含有2个m的对字符串匹配的⽅式:
where name = 'ee' #查找name是‘ee’的数据
where name like 'yu%' #查找以yu开头的数据
where name regexp 'euu$' #查找以euu结尾的数据