美文网首页
走向DBA之SQL语句(DQL)

走向DBA之SQL语句(DQL)

作者: 国王12 | 来源:发表于2019-06-19 21:07 被阅读0次

    select 查看

    一、作用:

    获取MySQL中的数据行信息

    二、单独使用select

    2.1获取参数信息

    语法:select @@xxx
    mysql> select @@port;      获取端口号                                              
    +--------+
    | @@port |
    +--------+
    |   3306 |
    +--------+
    1 row in set (0.00 sec)
    

    2.2模糊匹配获取参数信息

    语法:like '%内容%'
    mysql> show variables like 'wait_%'; 查看所有参数信息中的以wait_开头的参数
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | wait_timeout  | 28800 |
    +---------------+-------+
    1 row in set (0.00 sec)
    

    2.3调用函数

    mysql> select now();          查看当前时间
    mysql> select version();      查看MySQL版本
    mysql> select databse();      查看当前在哪个库
    ......
    

    三、SQL92便准语法

    3.1select 语法执行顺序(单表)

    select  开始  --->
    from    --->
    where   --->
    group by   --->
    select 后执行条件   --->
    having   --->
    order by   --->
    limit
    

    3.2select语句具体应用及人类可读解释说明

    单表子句from

    1.from    数据来自哪里
    select * from world.city;          查看world库下city表的所有数据信息
    
    select name,population from city;  查看city表的name和population列
    

    单表子句where

    2.where 匹配条件:(等值查询=,不等值查询<,>,<=,>=,<>,)
                      (模糊匹配 like,逻辑连接符号:and,or)
    等值匹配
    select * from teacher where name='oldboy' ;  查看teacher表中name列等于oldboy的行
    
    不等值匹配
    select * from sc where score>80;             查看sc表中score列大于80的所有行
    
    模糊匹配
    select * from teacher where name like '王'%; 查看teacher表中name列以'王'开头的所有行
    
    #注意,模糊匹配%尽量放结尾,也就是匹配以什么开头的,%放在开头或者两头都放,虽然可以执行,但是数据太大的时候,效率很低!
    
    逻辑连接符匹配
    select * from sc where score>60 and score<80; 查找成绩大于60同时小于80的(and逻辑连接符,需要满足两边条件)
    select * from sc where score>90 or score<20; 查找成绩大于90或者小于20的(or逻辑连接符,满足一个条件即可输出,两个条件都满足,都输出)
    

    group by + 常用聚合函数

    group by 可以理解为根据 by后面的条件进行分组(站队)方便统计,by后面跟一个列或多个列
    
    介绍一些常用聚合函数:
    AVG()           平均值
    COUNT()         计数
    SUM()           数值之和
    MAX()           最大值
    MIN()           最小值
    GROUP_CONCAT()  一行显示查到的内容
    
    group by 配合聚合函数具体用法:
    统计每个学生的总成绩
    select name,sum(score) from sc group by nob;
          名字列  成绩之和       sc表    按照nob(序列号)排队
    拿什么站队?
    nob序列号(主键,或者出现在select后,或者出现在函数里)
    拿什么统计?
    学生名,name
    统计的是什么?
    成绩总和
    这里不太好理解,下边写到多表连接查询的时候,还会说明
    

    having

    说明:在select查看匹配条件之后,再做处理,相当于linux下的管道
    
    统计中国每个省的总人数,且纸打印小于一百万的。
    SELECT district,SUM(Population)
    FROM city
    WHERE countrycode='chn'
    GROUP BY district
    HAVING SUM(Population) < 1000000 ;
    

    order by

    理解为排序
    
    查看中国每个省的总人数,且从大到小排序
    SELECT  district ,SUM(population) FROM city 
    WHERE countrycode='CHN'
    GROUP BY district 
    ORDER BY SUM(population) DESC  ;  
    默认时从小到大排序,加desc时从大到小排序
    

    limit

    理解为截取几行,和linux下cut -c差不多
    
    select *
    from world.city
    where countrycode='CHN' 
    order by population desc
    limit 10;
    显示十行
    
    select *
    from world.city
    where countrycode='CHN' 
    order by population desc
    limit 5,5;
    跳过前五行,显示五行(从第六行开始显示,显示五行。就是第六行到第十行)
    
    limit m,n   跳过m行,显示n行
    

    四、多表连接

    4.1什么时候用?

    需要查询的信息来自不同的表时,需要使用多表连接的方法来查询

    4.2怎么去多表连接查询?

    4.2.1传统的连接,基于where条件

    第一步:找表与表之间的关系列
    第二部:排列查询条件
    实施代码:

    查人口数量小于一千人的城市,所在国家的国土面积(城市名,国家名,国土面积)
    select city.name,country.name,country.surfacearea
    from city,country
    where city.countrycode = country.code
    and city.population<1000
    本方法现在很少使用,因此不过多阐述
    

    4.2内连接(多表连接查询的重点*****)

    语法介绍:

    关键词: join on
    1.找到表与表之间的关系列    A表的x列,B表的y列
    2.将两个表放在join两边     A join B
    3.将关联条件放在on后边     on A.x=B.y
    4.将所有的查询条件进行罗列 
    
    select A.m,B.n
    from  
    A  join  B
    on A.x=B.y
    where 
    group by 
    order by 
    limit
    
    可以理解为,join将两表的关系列(内容相同列)为条件,把两表合为一个表
    
    image.png

    举例说明:

    clipboard.png
    --- 2. 查询oldguo老师和他教课程名称
    SELECT teacher.tname ,course.cname
    FROM teacher 
    JOIN course 
    ON teacher.tno=course.tno
    WHERE teacher.tname='oldguo';
    解释说明:select 后边为要查询的内容来自xx表的xx列(老师名字列和课程名称列),join前后为信息来源的两张表,
    on后边写的两张表的关系列(内容相同),查询条件是teacher表tname列等于oldguo的行。
    
    查每一科成绩的总成绩
    select course.cno,course.cname,sum(score.score)
    from
    course join score
    on course.cno=score.cno
    group by score.cno;
    解释说明:sekect后边写的是要查询的数据来自课程表下的顺序列,课程表下的课程名称列,和成绩表下的成绩列并求和。
    join前后为信息来源的两张表,on后边是两张表的数据关联列,group by ,按照成绩的序列号(主键站队)
    
    --- 4. 查询oldguo老师教的学生姓名列表
    SELECT teacher.tname,GROUP_CONCAT(student.sname)
    FROM teacher 
    JOIN course
    ON teacher.tno = course.tno
    JOIN score
    ON course.cno = score.cno
    JOIN student 
    ON score.sno = student.sno
    WHERE teacher.tname='oldguo'
    GROUP BY teacher.tname;
    
    --- 5. 查询所有老师教的学生姓名列表
    SELECT teacher.tname,GROUP_CONCAT(student.sname)
    FROM teacher 
    JOIN course
    ON teacher.tno = course.tno
    JOIN sc
    ON course.cno = sc.cno
    JOIN student 
    ON sc.sno = student.sno
    GROUP BY teacher.tno;
    
    --- 6. 查询oldboy老师教的不及格学生的姓名
    SELECT teacher.tname,GROUP_CONCAT(student.sname)
    FROM teacher 
    JOIN course
    ON teacher.tno = course.tno
    JOIN score
    ON course.cno = score.cno
    JOIN student 
    ON score.sno = student.sno
    WHERE teacher.tname='oldguo'
    and score.score<60
    GROUP BY teacher.tname;
    
    --- 7. 统计zhang3,学习了几门课
    select student.sname,COUNT(course.cname)
    from
    student join score
    on
    student.sno=score.sno
    join course
    on
    score.cno=course.cno
    where student.sname='zhang3'
    group by student.sno;
    
    --- 8. 查询zhang3,学习的课程名称有哪些?
    select student.sname,GROUP_CONCAT(course.cname)
    from
    student join score
    on
    student.sno=score.sno
    join course
    on
    score.cno=course.cno
    where student.sname='zhang3'
    group by student.sno;
    
    --- 9. 查询oldguo老师教的学生名.
    SELECT teacher.tname,GROUP_CONCAT(student.sname)
    FROM teacher 
    JOIN course
    ON teacher.tno = course.tno
    JOIN score
    ON course.cno = score.cno
    JOIN student 
    ON score.sno = student.sno
    WHERE teacher.tname='oldguo'
    GROUP BY teacher.tname;
    
    --- 10.查询oldguo所教课程的平均分数
    select teacher.tname,AVG(score.score)
    from
    teacher join course
    on
    teacher.tno=course.tno
    join score
    on
    course.cno=score.cno
    where teacher.tname='oldguo'
    group by teacher.tname;
    
    --- 11.每位老师所教课程的平均分,并按平均分排序
    select teacher.tname,course.cname,AVG(score.score)
    from
    teacher join course
    on teacher.tno=course.tno
    join score
    on course.cno=score.cno
    group by teacher.tno,course.cno
    order by AVG(score.score);
    

    4.3外连接:

    外连接分:

    左外连接 即:left join          
    右外连接 即: right join
    注意:需要把where换成and(如果不换的话,不会起到外连接的效果,只会让左表(或右表)当作驱动表,助力查询)
    
    解释:拿左外连接来讲,在正常取出两表关联列之外,把左表的全部数据也取出来,那么右边的那个表没有这些数据怎么办呢?嘿嘿,用null填充。注意,这种外连接的方法,不仅需要加left(一般都加这个)或者right之外,同时需要把where改成and,才算真正的左外连接。

    示例:

    正常连表查询:
    mysql> select teacher.tname,course.cname
        -> from teacher join course
        -> on teacher.tno=course.tno
        -> where  teacher.tname='oldguo';
    +--------+-------+
    | tname  | cname |
    +--------+-------+
    | oldguo | mysql |
    +--------+-------+
    1 row in set (0.00 sec)
    
    左外连接连表查询:
    mysql> select teacher.tname,course.cname
        -> from teacher left join course
        -> on teacher.tno=course.tno
        -> and  teacher.tname='oldguo';
    +--------+-------+
    | tname  | cname |
    +--------+-------+
    | oldguo | mysql |
    | oldboy | NULL  |  ------->看到了吧,把左表的全部列打印出来了,右边以null填充。
    | hesw   | NULL  |
    +--------+-------+
    3 rows in set (0.00 sec)
    

    补充语句:

    distinct() 对列去重

    select distinct(cno) from score;
    合并(去重)cno列
    

    效果:

    去重前:
    mysql> select count(name) from world.city;
    +-------------+
    | count(name) |
    +-------------+
    |        4079 |
    +-------------+
    1 row in set (0.08 sec)
    
    去重后:
    mysql> select count(distinct(name)) from world.city;
    +-----------------------+
    | count(distinct(name)) |
    +-----------------------+
    |                  3998 |
    +-----------------------+
    1 row in set (0.00 sec)
    

    别名:AS

    说明:和linux命令行设置别名差不多.

    1.表别名:

    在这里,别名只能在本次select语句中使用,一般别名在from后设置,设置之后,整条select语句都可以运用别名。
    用法:from 表名 AS 别名

    不加别名:

    select teacher.tname,group_concat(student.sname)
    from
    teacher join course
    on teacher.tno=course.tno
    join score
    on course.cno=score.cno
    join student
    on score.sno=student.sno
    where teacher.tname='oldguo' and score.score<60
    group by teacher.tno
    
    添加别名:
    select te.tname,group_concat(st.sname)
    from
    teacher AS te join course AS co
    on te.tno=co.tno
    join score AS sc
    on co.cno=sc.cno
    join student AS st
    on sc.sno=st.sno
    where te.tname='oldguo' and sc.score<60
    group by te.tno;
    #建议:一般别名设置为表名的前两个字符,简单且不易弄混
    

    2.列别名:

    作用:打印输出的时候,把表头更改为你设置的别名

    不加别名

    mysql> select count(distinct(name)) from world.city;
    +-----------------------+
    | count(distinct(name)) |
    +-----------------------+
    |                  3998 |
    +-----------------------+
    1 row in set (0.01 sec)
    

    添加别名:

    mysql> select count(distinct(name)) AS n from world.city;
    +------+
    | n    |
    +------+
    | 3998 |
    +------+
    1 row in set (0.00 sec)
    
    注意:设置别名的AS可以大写,可以小写,也可以不写,但是建议用大写,这样一眼就可以看出设置了别名。
    

    相关文章

      网友评论

          本文标题:走向DBA之SQL语句(DQL)

          本文链接:https://www.haomeiwen.com/subject/jpmqqctx.html