mysql学习录(三)多表查询、子查询、分页查询、case语句、单行函数

小技巧:输入了好几条语句,但是又不想执行,又删不掉,这时候就需要使用 \c

mysql> SELECT
    ->
    -> \c
mysql>
多表查询

把连接条件写在 where 之后的这种方式叫做隐性连接,他的功能和内连接的功能是一样的,而带 on 的连接方式叫做显性连接。现在随着数据库的规范和发展,大多用显性连接,很少用隐性连接。

1.笛卡尔积现象

在多表连接查询时,如果定义了无效连接或者漏写连接条件,就会产生笛卡尔积现象。所谓笛卡尔积就是每个表的每一行都和其它表的每一行组合,假设两个表的总行数一个 x,一个 y,则返回笛卡尔积 x*y。

2.等值连接查询

寻找俩表中字段名称相等,数据类型相同的字段进行连接,会自动去重重复列(如果有多个字段符合要求,那么他们会被作为自然连接的条件)又叫自然连接

最常见的,通常是在存在主键外键关联关系之间的表之间进行,并将连接条件设置为有关系的列【主键-外键】,使用 ”=“ 连接相关表。避免笛卡尔积现象,n个表等值连接时至少需要 n-1 个等值连接条件。

mysql>-- emp员工表的 dept_id 字段是 dept部门表的主键 id
mysql> desc dept;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| DEPTNO   | int         | NO   | PRI | NULL    |       |
| DNAME    | varchar(14) | YES  |     | NULL    |       |
| LOCATION | varchar(13) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> desc emp;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO    | int         | NO   | PRI | NULL    |       |
| ENAME    | varchar(10) | YES  |     | NULL    |       |
| JOB      | varchar(9)  | YES  |     | NULL    |       |
| MANAGER  | int         | YES  |     | NULL    |       |
| HIREDATE | date        | YES  |     | NULL    |       |
| SAL      | double(7,2) | YES  |     | NULL    |       |
| COMM     | double(7,2) | YES  |     | NULL    |       |
| DEPTNO   | int         | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
8 rows in set (0.00 sec)

mysql> -- 隐性连接的写法
mysql> select d.dname, e.empno, e.ename from dept as d, emp e where d.deptno = e.deptno;
+------------+-------+--------+
| dname      | empno | ename  |
+------------+-------+--------+
| RESEARCH   |  7369 | SMITH  |
| SALES      |  7499 | ALLEN  |
| SALES      |  7521 | WARD   |
| RESEARCH   |  7566 | JONES  |
| SALES      |  7654 | MARTIN |
| SALES      |  7698 | BLAKE  |
| ACCOUNTING |  7782 | CLARK  |
| RESEARCH   |  7788 | SCOTT  |
| ACCOUNTING |  7839 | KING   |
| SALES      |  7844 | TURNER |
| RESEARCH   |  7876 | ADAMS  |
| SALES      |  7900 | JAMES  |
| RESEARCH   |  7902 | FORD   |
| ACCOUNTING |  7934 | MILLER |
+------------+-------+--------+
14 rows in set (0.00 sec)

as 给别名 ,一般表的别名直接用空格隔开 省略as

3.自连接查询

一个表中进行多表查询,。

员工和员工上级都在员工表中,用manager_id 来标识员工上级

select e1.empno as 员工编号, e1.ename as 员工姓名, e2.empno as 领导编号, e2.ename as 领导姓名 from emp e1, emp e2 where e1.manager_id = e2.empno;
4.内连接查询

关键字:表1 inner join 表2 on 连接条件 (inner可以省略)

语句:select * from a_table a inner join b_table b on a.a_id = b.b_id;

说明:组合两个表中的记录,返回关联字段相符的记录,也就是返回两个表的交集部分。
自连接查询也可以用内连接来实现:

SELECT e1.empno AS 员工编号, e1.ename AS 员工姓名, e2.empno AS 领导编号, e2.ename AS 领导姓名 FROM emp e1 JOIN emp e2 ON e1.manager_id = e2.empno;

条件不一定是两个表是主外键关系,返回的是符合条件的记录

5.外连接查询

外连接分为 left outer join(左外连接) 和 right outer join (右外连接),outer可以省略。

关键字join左边的叫左表,右边的叫右表

a. 左连接表示显示左表的全部数据,右表满足连接条件的数据,不满足的用null值填充;右连接表示显示右表的全部数据,左表满足连接条件的数据,不满足null值填充。

b. 结果集要包含右表中所有匹配的行,若右表中有的项在左表中没有对应的项,以null值填充。
在这里,join指定的表为主表,即右表为主表。(哪个表中所有行都显示了,就是主表)

mysql> -- 左外连接 ( OUTER 关键字是可以省略的 )
mysql> SELECT * FROM t_class c LEFT OUTER JOIN t_major m ON c.major_id = m.id ;
+----+----------+----------+------+------------------+
| id | name     | major_id | id   | name             |
+----+----------+----------+------+------------------+
|  1 | 软件一班 |        2 |    2 | 软件工程         |
|  2 | 软件二班 |        2 |    2 | 软件工程         |
|  3 | 计科一班 |        4 |    4 | 计算机科学与技术 |
|  4 | 计科二班 |        4 |    4 | 计算机科学与技术 |
|  5 | 卓越班   |     NULL | NULL | NULL             |
|  6 | 东坡班   |     NULL | NULL | NULL             |
+----+----------+----------+------+------------------+
6 rows in set (0.00 sec)

mysql> -- 右外连接 ( OUTER 关键字是可以省略的 )
mysql> SELECT * FROM t_class c RIGHT OUTER JOIN t_major m ON c.major_id = m.id ;
+------+----------+----------+----+------------------+
| id   | name     | major_id | id | name             |
+------+----------+----------+----+------------------+
| NULL | NULL     |     NULL |  5 | 信息对抗         |
| NULL | NULL     |     NULL |  3 | 动物医学         |
| NULL | NULL     |     NULL |  1 | 土木工程         |
|    3 | 计科一班 |        4 |  4 | 计算机科学与技术 |
|    4 | 计科二班 |        4 |  4 | 计算机科学与技术 |
|    1 | 软件一班 |        2 |  2 | 软件工程         |
|    2 | 软件二班 |        2 |  2 | 软件工程         |
+------+----------+----------+----+------------------+
7 rows in set (0.00 sec)

全外连接( MySQL不支持 )
相当于左外和右外连接的并集
SELECT * FROM t_class c FULL OUTER JOIN t_major m ON c.major_id = m.id ;

子查询
1.单行子查询

返回单行单列

2.多行子查询

返回单行多列 (使用了成对比较))

3.多列子查询

返回多行单列

4.相关子查询

子查询使用了外部SQL的某些表或列 (但是外部SQL不可使用子查询中的表和列)

5.嵌套子查询:

在子查询内部可以继续嵌套子查询

分页查询

使用 lilmit 实现分页查询
语法:limit a , b 第一个参数表示从第几条开始查(用页数索引(0开始)* 每页记录数), 第二个表示一页查几条

-- 显示第一条到第五条记录
select * from emp limit 0,5;
CASE语句
1.语法:
CASE 
	WHEN 条件1 THEN 结果1
	WHEN 条件2 THEN 结果2
	...
	WHEN 条件n THEN 结果n
	ELSE 其余情况
END	
2.例子:
mysql> SELECT s.name 学生姓名 ,
    ->        c.name 课程名称 ,
    ->        CASE
    ->            WHEN x.score BETWEEN 90 AND 100 THEN 'A'
    ->            WHEN x.score > 80 THEN 'B'
    ->            WHEN x.score > 70 THEN 'C'
    ->            WHEN x.score > 60 THEN 'D'
    ->            ELSE 'E'
    ->        END AS 成绩等级
    -> FROM t_students s
    ->      JOIN t_scores x ON x.sid = s.id
    ->      JOIN t_courses c ON x.cid = c.id ;
+--------------+--------------+--------------+
| 学生姓名     | 课程名称     | 成绩等级     |
+--------------+--------------+--------------+
| 张无忌       | C++          | A            |
| 张无忌       | C++          | A            |
| 周芷若       | C++          | A            |
| 张三丰       | C++          | A            |
| 刘书妹       | C++          | E            |
| 刘书妹       | C++          | E            |
| 张无忌       | Java         | A            |
| 小昭         | Java         | A            |
| 吴莫愁       | Java         | D            |
| 赵敏         | Oracle       | B            |
| 张三丰       | Oracle       | E            |
| 周芷若       | HTML/CSS     | A            |
| 吴莫愁       | HTML/CSS     | C            |
| 刘书妹       | HTML/CSS     | E            |
+--------------+--------------+--------------+
14 rows in set (0.00 sec)

单行函数

SQL函数即数据库的内置函数,可以应用在SQL语句中实现特定功能,单行函数对于每一行的数据进行计算后得到一行输出结果;多行函数是多行数据参与运算得到一行输出结果。

1.字符函数
length()、 concat()、upper() 、lower()、substr()或substring()、 instr()、trim()、lpad()和rpad()replace() ;
大小写转换函数:upper,lower
mysql> SELECT upper('abc'), lower('ABC');
+--------------+--------------+
| upper('abc') | lower('ABC') |
+--------------+--------------+
| ABC          | abc          |
+--------------+--------------+
1 row in set (0.00 sec)
字符串连接函数:concat

连接字符串

mysql> SELECT concat('tx', 'sql');
+---------------------+
| concat('tx', 'sql') |
+---------------------+
| txsql               |
+---------------------+
1 row in set (0.00 sec)
获取子字符串函数:substr

用于字符串截取 第一个参数是被截取的字符串 第二个参数是从第几位开始截取 空格也算一个字符

mysql> SELECT substr('java sql js', 5);
+--------------------------+
| substr('java sql js', 5) |
+--------------------------+
|  sql js                  |
+--------------------------+
1 row in set (0.00 sec)

其它的字符串函数:
  1. length(字符串); :获取字符串的长度
  2. instr('父字符串', '子字符串'); :获取子字符串在父字符串中的索引 从1开始 空格也算
  3. ltrim(' java web'); :去掉字符串左侧空格
  4. rtrim('java web '); :去掉右侧的空格
  5. trim(' java web '); :去掉两侧的空格
  6. replace('字符串', '要替换的子字符串', '替换字符串'); :第一个是父字符串 第二个要替换的子字符串 替换的字符串
2.数学函数
round()、ceil()和floor()truncate()mod();
  • round(x, [y]) :对指定的 X 进行四舍五入操作 可以指定保留位数 y 可以是负值
  • truncate(x, y) :对指定的 X 进行截取操作,可以指定保留的数值位数
  • ceil(x) :返回不小于指定值x的最小整数 比如 x是4.5返回5
  • floor(x) :返回不大于x的最大整数 比如x是8.1返回8
  • abs(x) :取绝对值
  • mod(x, y) :取x除以y的余数
  • sign(x) :取x的符号函数 负数(-1),0,正数 (1)
  • power(x, y) :取x的y次幂 x=2 ,y=3,则 2的3次方等于8
  • sqrt(x) :取x的二次方根
3.日期函数
now()、curdate()、curtime()、年、月、日、小时、分钟、秒、str_to_date()和date_format();
当前日期函数
日期截取函数
日期增加函数
特例:
日期格式符
1.概念:

格式符是描述日期的格式符号,用字母描述日期中特定的部分,以%开头,例如 %m表示日期中的月份。

2.格式符表:
格式描述
%a缩写星期名
%b缩写月名
%c月,数值
%D带有英文前缀的月中的天
%d月的天,数值(00-31)
%e月的天,数值(0-31)
%f微秒
%H小时(00-23)
%h小时(01-12)
%I小时(01-12)
%i分钟,数值(00-59)
%j年的天(001-366)
%k小时(0-23)
%l小时(1-12)
%M月名
%m月,数值(00-12)
%pAM 或 PM
%r时间,12-小时(hh:mm:ss AM 或 PM)
%S秒(00-59)
%s秒(00-59)
%T时间, 24-小时(hh:mm:ss)
%U周(00-53)星期日是一周的第一天
%u周(00-53)星期一是一周的第一天
%V周(01-53)星期日是一周的第一天,与 %X 使用
%v周(01-53)星期一是一周的第一天,与 %x 使用
%W星期名
%w周的天(0=星期日, 6=星期六)
%X年,其中的星期日是周的第一天,4 位,与 %V 使用
%x年,其中的星期一是周的第一天,4 位,与 %v 使用
%Y年,4 位
%y年,2 位
查询今天
/*
  NOW() 函数返回当前的日期和时间。
  TO_DAYS()函数返回日期和年份0(日期"0000-00-00")之间的天数。
*/
SELECT * FROM cpidata WHERE TO_DAYS( 时间字段名 ) = TO_DAYS(NOW());
查询昨天
/*
  NOW() 函数返回当前的日期和时间。
  TO_DAYS()函数返回日期和年份0(日期"0000-00-00")之间的天数。
*/
SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ) - TO_DAYS( 时间字段名) = 1
查询本周
/*
  YEARWEEK()返回年份和星期
  DATE_FORMAT(被格式化的日期,格式符)日期格式化函数
*/
SELECT * FROM 表名 WHERE YEARWEEK(DATE_FORMAT(日期字段名,'%Y-%m-%d')) = YEARWEEK(NOW());
查询上周
/*
  YEARWEEK()返回年份和星期
  DATE_FORMAT(被格式化的日期,格式符)日期格式化函数
*/
SELECT * FROM 表名 WHERE YEARWEEK(DATE_FORMAT(日期字段名,'%Y-%m-%d')) = YEARWEEK(NOW())-1;
查询近7天
/*
  DATE_SUB() 函数从日期减去指定的时间间隔
  DATE_SUB(合法的日期表达式,INTERVAL 希望添加的时间间隔 时间类型)
  CURDATE() 函数返回当前的日期。
*/
SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(时间字段名)
查询近30天
/*
  DATE_SUB() 函数从日期减去指定的时间间隔
  DATE_SUB(合法的日期表达式,INTERVAL 希望添加的时间间隔 时间类型)
  CURDATE() 函数返回当前的日期。
*/
SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(时间字段名)
查询本月
/*
  DATE_FORMAT(被格式化的日期,格式符)日期格式化函数
*/
SELECT * FROM 表名 WHERE DATE_FORMAT( 时间字段名, '%Y%m' ) = DATE_FORMAT( CURDATE( ) , '%Y%m' );
查询上一月
/*
  PERIOD_DIFF(第一个日期,第二个日期)函数返回两日期之间的差异。结果以月份计算
*/
SELECT * FROM 表名 WHERE PERIOD_DIFF( DATE_FORMAT( NOW( ) , '%Y%m' ) , DATE_FORMAT( 时间字段名, '%Y%m' ) ) =1
查询本季度
/*
 QUARTER(日期)返回日期的季度:
*/
SELECT * FROM 表名 WHERE QUARTER(日期字段名)=QUARTER(NOW());
查询上季度
/*
 QUARTER(日期)返回日期的季度:
 DATE_SUB() 函数从日期减去指定的时间间隔
 DATE_SUB(合法的日期表达式,INTERVAL 希望添加的时间间隔 时间类型)
*/
SELECT * FROM 表名 WHERE QUARTER(日期字段名)=QUARTER(DATE_SUB(NOW(),INTERVAL 1 QUARTER));
查询本年度
/*
 year(日期字段名)返回日期中的年份
*/
SELECT * FROM 表名 WHERE YEAR(日期字段名)=YEAR(NOW());
查询上年度
/*
 year(日期字段名)返回日期中的年份
 DATE_SUB() 函数从日期减去指定的时间间隔
 DATE_SUB(合法的日期表达式,INTERVAL 希望添加的时间间隔 时间类型)
*/
SELECT * FROM 表名 WHERE YEAR(日期字段名)=YEAR(DATE_SUB(NOW(),INTERVAL 1 YEAR));
4.其它内置系统函数
version()database()user();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值