diff --git "a/03\350\265\226\345\277\203\345\246\215/2.16 \350\257\255\345\217\245\350\247\204\350\214\203\347\255\211.md" "b/03 \350\265\226\345\277\203\345\246\215/2.16 \350\257\255\345\217\245\350\247\204\350\214\203\347\255\211.md" similarity index 100% rename from "03\350\265\226\345\277\203\345\246\215/2.16 \350\257\255\345\217\245\350\247\204\350\214\203\347\255\211.md" rename to "03 \350\265\226\345\277\203\345\246\215/2.16 \350\257\255\345\217\245\350\247\204\350\214\203\347\255\211.md" diff --git "a/03\350\265\226\345\277\203\345\246\215/2.17 MySQL\350\257\255\345\217\245.md" "b/03 \350\265\226\345\277\203\345\246\215/2.17 MySQL\350\257\255\345\217\245.md" similarity index 100% rename from "03\350\265\226\345\277\203\345\246\215/2.17 MySQL\350\257\255\345\217\245.md" rename to "03 \350\265\226\345\277\203\345\246\215/2.17 MySQL\350\257\255\345\217\245.md" diff --git "a/03\350\265\226\345\277\203\345\246\215/2.21 \347\272\246\346\235\237.md" "b/03 \350\265\226\345\277\203\345\246\215/2.21 \347\272\246\346\235\237.md" similarity index 99% rename from "03\350\265\226\345\277\203\345\246\215/2.21 \347\272\246\346\235\237.md" rename to "03 \350\265\226\345\277\203\345\246\215/2.21 \347\272\246\346\235\237.md" index 5031aefc27249dac88cc2942cbf7fb4c6e8f8950..64433ab552ef9c1965355a152a52d0883b38ce84 100644 --- "a/03\350\265\226\345\277\203\345\246\215/2.21 \347\272\246\346\235\237.md" +++ "b/03 \350\265\226\345\277\203\345\246\215/2.21 \347\272\246\346\235\237.md" @@ -431,7 +431,7 @@ CREATE TABLE employee ( title VARCHAR(10), birthday date NOT NULL, depid VARCHAR(5), - FOREIGN KEY(depid) REFERENCES department(depid) ON UPDATE CASCADE ON DELETE SET NULL + FOREIGN KEY(empid) REFERENCES department(depid) ON UPDATE CASCADE ON DELETE SET NULL ); ``` diff --git "a/03 \350\265\226\345\277\203\345\246\215/2.23 \346\237\245\350\257\242select\350\257\255\345\217\245\345\222\214\350\277\220\347\256\227\347\254\246.md" "b/03 \350\265\226\345\277\203\345\246\215/2.23 \346\237\245\350\257\242select\350\257\255\345\217\245\345\222\214\350\277\220\347\256\227\347\254\246.md" new file mode 100644 index 0000000000000000000000000000000000000000..6b0181a1e8bcb963cc5eaf95d3663d8fe0596e21 --- /dev/null +++ "b/03 \350\265\226\345\277\203\345\246\215/2.23 \346\237\245\350\257\242select\350\257\255\345\217\245\345\222\214\350\277\220\347\256\227\347\254\246.md" @@ -0,0 +1,361 @@ +# 2.23 查询select语句和运算符 + +### select语句格式: + +```mysql +SELECT 字段列表 FROM 表名称; + +SELECT 字段列表 FROM 表名称 WHERE 条件; +``` + +### 使用别名(临时名称) + +```mysql +select 字段名1 as "别名1", 字段名2 as "别名2" from 表名称 as 别名; +``` + +- 列的别名有空格时,请加双引号。**==列的别名==中没有空格时,双引号可以加也可以不加**。 +- ==**表的别名不能加双引号**==,表的别名中间不能包含空格。 +- as大小写都可以,as也完全可以省略。 + +```mysql +示例: +mysql> select id "学号",name "姓名" from student; ++------+------+ +| 学号 | 姓名 | ++------+------+ +| 1 | 张三 | +| 2 | 李四 | ++------+------+ +2 rows in set (0.00 sec) + +mysql> select id 学号,name 姓名 from student; ++------+------+ +| 学号 | 姓名 | ++------+------+ +| 1 | 张三 | +| 2 | 李四 | ++------+------+ +2 rows in set (0.00 sec) +``` + +### 结果去重 + +mysql可以在查询结果中使用distinct关键字去重。 + +```mysql +select distinct 字段列表 from 表名称 【where 条件】; + +示例: +select distinct did from t_employee; +``` + +### 算术运算符 + +```mysql +加:+ + 在MySQL +就是求和,没有字符串拼接 +减:- +乘:* +除:/ div(只保留整数部分) + div:两个数相除只保留整数部分 + /:数学中的除 +模:% mod + +mysql中没有 +=等运算符 +``` + +### 比较运算符 + +```mysql +大于:> +小于:< +大于等于:>= +小于等于:>= +等于:= 不能用于null判断 +不等于:!= 或 <> 不能用于null判断 +判断是null 用 is null 或 用 <=> null +判断不是null is not null +``` + +### 区间或集合范围比较运算符 + +```mysql +区间范围:between x and y + not between x and y +集合范围:in (x,x,x) + not in(x,x,x) +between ... and ... 结果包含两端的边界 + +示例: +#查询薪资在[10000,15000] +select * from t_employee where salary>=10000 && salary<=15000; +select * from t_employee where salary between 10000 and 15000; + +#查询籍贯在这几个地方的 +select * from t_employee where work_place in ('北京', '浙江', '江西'); + +#查询薪资不在[10000,15000] +select * from t_employee where salary not between 10000 and 15000; + +#查询籍贯不在这几个地方的 +select * from t_employee where work_place not in ('北京', '浙江', '江西'); +``` + +### 模糊匹配比较运算符 + +%:代表任意个字符 + +_:代表一个字符,如果两个下划线代表两个字符 + +```mysql +示例: +#查询名字中包含'冰'字 +select * from t_employee where ename like '%冰%'; + +#查询名字以‘雷'结尾的 +select * from t_employee where ename like '%远'; + +#查询名字以’李'开头 +select * from t_employee where ename like '李%'; + +#查询名字有冰这个字,但是冰的前面只能有1个字 +select * from t_employee where ename like '_冰%'; + +#查询当前mysql数据库的字符集情况 +show variables like '%character%'; +``` + +### 逻辑运算符 + +```mysql +逻辑与:&& 或 and +逻辑或:|| 或 or +逻辑非:! 或 not +逻辑异或: xor + +示例: +#查询薪资高于15000,并且性别是男的员工 +select * from t_employee where salary>15000 and gender='男'; +select * from t_employee where salary>15000 && gender='男'; + +select * from t_employee where salary>15000 & gender='男';#错误得不到值 &按位与 +select * from t_employee where (salary>15000) & (gender='男'); + +#查询薪资高于15000,或者did为1的员工 +select * from t_employee where salary>15000 or did = 1; +select * from t_employee where salary>15000 || did = 1; + +#查询薪资不在[15000,20000]范围的 +select * from t_employee where salary not between 15000 and 20000; +select * from t_employee where !(salary between 15000 and 20000); + +#查询薪资高于15000,或者did为1的员工,两者只能满足其一 +select * from t_employee where salary>15000 xor did = 1; +select * from t_employee where (salary>15000) ^ (did = 1); +``` + +### 关于null值的问题、 + +```mysql +#(1)判断时 +xx is null +xx is not null +xx <=> null + +#(2)计算时 +ifnull(xx,代替值) 当xx是null时,用代替值计算 + +示例: +#查询员工的实发工资,实发工资 = 薪资 + 薪资 * 奖金比例 +select ename , salary + salary * commission_pct "实发工资" from t_employee; #失败,当commission_pct为null,结果都为null + +select ename ,salary , commission_pct, salary + salary * ifnull(commission_pct,0) "实发工资" from t_employee; +``` + +### 位运算符 + +```mysql +左移:<< +右移:>> +按位与:& +按位或:| +按位异或:^ +按位取反:~ +``` + + + +# 作业 + +## 第1题:员工表 + +| **id** | **name** | **sex** | **tel** | **addr** | **salary** | +| ------ | -------- | ------- | ------------ | -------- | ---------- | +| 10001 | 张一一 | 男 | 13456789000 | 广东韶关 | 10010.58 | +| 10002 | 刘小红 | 女 | 13454319000 | 广东江门 | 12010.21 | +| 10003 | 李四 | 男 | 0751-1234567 | 广东佛山 | 10040.11 | +| 10004 | 刘小强 | 男 | 0755-5555555 | 广东深圳 | 15010.23 | +| 10005 | 王艳 | 女 | NULL | 广东广州 | 14050.16 | + +```mysql +CREATE DATABASE test03 CHARSET utf8; +USE test03; + +CREATE TABLE employee( + id INT, + `name` VARCHAR(20), + sex VARCHAR(20), + tel VARCHAR(20), + addr VARCHAR(50), + salary FLOAT +); + +INSERT INTO employee(id,`name`,sex,tel,addr,salary)VALUES +(10001,'张一一','男','13456789000','广东韶关',10010.58), +(10002,'刘小红','女','13454319000','广东江门',12010.21), +(10003,'李四','男','0751-1234567','广东佛山',10040.11), +(10004,'刘小强','男','0755-5555555','广东深圳',15010.23), +(10005,'王艳','男',NULL,'广东广州',14050.16); +``` + +**要求1:**查询出薪资在12000~13000之间的员工信息。 + +```mysql +SELECT * FROM employee WHERE salary BETWEEN 12000 AND 13000; +``` + +**要求2:**查询出姓“刘”的员工的工号,姓名,家庭住址。 + +```mysql +SELECT id,`name`,addr FROM employee WHERE `name` LIKE '刘%'; +``` + +**要求3:**将“李四”的家庭住址改为“广东韶关” + +```mysql +UPDATE employee SET addr = '广东韶关' WHERE `name` = '李四'; +``` + +**要求4:**查询出名字中带“小”的员工 + +```mysql +SELECT `name` FROM employee WHERE `name` LIKE '%小%'; +``` + +**要求5:**查询出薪资高于11000的男员工信息 + +```mysql +SELECT * FROM employee WHERE salary>11000 AND sex='男'; +``` + +**要求6:**查询没有登记电话号码的员工 + +```mysql +SELECT `name` FROM employee WHERE tel is NULL; +``` + +**要求7:**查询薪资高于12000或者家是广东深圳、广州的男员工 + +```mysql +SELECT `name` FROM employee WHERE sex = '男' AND salary = 12000 OR addr = '广东深圳' OR addr='广东广州'; +``` + +**要求8:**查询每个员工的年薪,显示“姓名、年薪” + +```mysql +SELECT `name`,salary FROM employee; +``` + + + +## 第2题:国家信息表 + +countries_info表中存储了国家名称、所属大陆、面积、人口和 GDP 值。 + +```mysql +DROP TABLE IF EXISTS `countries_info`; +CREATE TABLE `countries_info`( + `name` VARCHAR(100), + `continent` VARCHAR(100), + `area` INT, + population INT, + gdp BIGINT +); + +INSERT INTO countries_info VALUES +('Afghanistan','Asia',652230,25500100,20343000000), +('Albania','Europe',28748,2831741,12960000000), +('Algeria','Africa',2381741,37100000,188681000000), +('Andorra','Europe',468,78115,3712000000), +('Angola','Africa',1246700,20609294,100990000000); +``` + +表数据样例: + +```mysql ++-------------+-----------+---------+------------+--------------+ +| name | continent | area | population | gdp | ++-------------+-----------+---------+------------+--------------+ +| Afghanistan | Asia | 652230 | 25500100 | 20343000000 | +| Albania | Europe | 28748 | 2831741 | 12960000000 | +| Algeria | Africa | 2381741 | 37100000 | 188681000000 | +| Andorra | Europe | 468 | 78115 | 3712000000 | +| Angola | Africa | 1246700 | 20609294 | 100990000000 | ++-------------+-----------+---------+------------+--------------+ +``` + +**要求1:** 查询大国 的国家名称、人口和面积。 + +如果一个国家满足下述两个条件之一,则认为该国是 大国 : + +- 面积至少为 300万平方公里(即,3000000 km2) + +- 人口至少为 2500 万(即 25000000) + + ```mysql + SELECT `name`,area,population FROM countries_info WHERE area>3000000 OR population>=25000000; + ``` + +**要求2:**查询属于亚洲的国家名称、所属大陆、面积、人口和 GDP 值 + +```mysql +SELECT * FROM countries_info WHERE continent = 'Asia'; +``` + +**要求3:**查询国土面积不足1万平方公里且人口不走10万人的国家信息 + +```mysql +SELECT * FROM countries_info WHERE area<10000 AND population<100000; +``` + +**要求4:**查询国家名字中包含“o“字母的国家信息 + +```mysql +SELECT * FROM countries_info WHERE `name` LIKE '%o%'; +``` + +**要求5:**查询GDP值超过10000000000的国家信息 + +```mysql +SELECT * FROM countries_info WHERE gdp>10000000000; +``` + +**要求6:**查询每个国家的人均贡献GDP值(GDP/人口总数)并显示为“国家名、人口、GDP值、人均贡献GDP值” + +```mysql +SELECT `name` 国家名,population 人口,gdp GDP值,gdp/population AS 人均贡献GDP值 FROM countries_info; +``` + +**要求7:**查询人均贡献GDP值低于1000的国家信息。 + +```mysql +SELECT * FROM countries_info WHERE gdp/population<1000; +``` + +**要求8:**查询每个国家的人均国土面积(面积/人口总数)并显示为“国家名、面积、人口、人均国土面积值” + +```mysql +SELECT `name` 国家名,population 人口,gdp GDP值,area/population AS 人均国土面积值 FROM countries_info; +``` + diff --git "a/03 \350\265\226\345\277\203\345\246\215/2.28 \345\205\263\350\201\224\346\237\245\350\257\242.md" "b/03 \350\265\226\345\277\203\345\246\215/2.28 \345\205\263\350\201\224\346\237\245\350\257\242.md" new file mode 100644 index 0000000000000000000000000000000000000000..9a4de388b0068a3f6d45295508f2b68f8ac1dbe7 --- /dev/null +++ "b/03 \350\265\226\345\277\203\345\246\215/2.28 \345\205\263\350\201\224\346\237\245\350\257\242.md" @@ -0,0 +1,540 @@ +# 2.28 关联查询 + +#### 分组函数 + +| **AVG(x) :求平均值** | **SUM(x):求总和** | +| ------------------------ | -------------------- | +| **MAX(x):求最大值** | **MIN(x):求最小值** | +| **COUNT(x):统计记录数** | | + +count(*)是对满足条件的(如果没有where条件,就是对所有记录)记录累加数量 + +count(常量值)等价于count(*) + +count(字段名/表达式) 只统计非NULL值的记录数 + +#### 单行函数 + +##### 数学函数 + +| 函数 | 用法 | +| ------------- | ------------------------------------------------------------ | +| ABS(x) | 返回x的绝对值 | +| CEIL(x) | 返回大于x的最小整数值 | +| FLOOR(x) | 返回小于x的最大整数值 | +| MOD(x,y) | 返回x/y的模 | +| RAND() | 返回0~1的随机值 | +| ROUND(x,y) | 返回参数x的四舍五入的有y位的小数的值 | +| TRUNCATE(x,y) | 返回数字x截断为y位小数的结果 | +| FORMAT(x,y) | 强制保留小数点后y位,整数部分超过三位的时候以逗号分割,并且返回的结果是文本类型的 | +| SQRT(x) | 返回x的平方根 | +| POW(x,y) | 返回x的y次方 | + +##### 字符串函数 + +| 函数 | 功能描述 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| CONCAT(S1,S2,……Sn) | 连接S1,S2,……Sn为一个字符串 | +| CONCAT_WS(s,S1,S2,……Sn) | 同CONCAT(S1,S2,…)函数,但每个字符串之间要加上s | +| CHAR_LENGTH(s) | 返回字符串s的字符数 | +| LENGTH(s) | 返回字符串s的字节数,和字符集有关 | +| LOCATE(str1,str)或 POSITION(str1 in str)或 INSTR(str,str1) | 返回子字符串str1在str中的开始位置 | +| UPPER(s)或UCASE(s) | 将字符串s的所有字母转成大写字母 | +| LOWER(s)或LCASE(s) | 将字符串s的所有字母转成小写字母 | +| LEFT(s,n) | 返回字符串s最左边的n个字符 | +| RIGHT(s,n) | 返回字符串s最右边的n个字符 | +| LPAD(str,len,pad) | 用字符串pad对str最左边进行填充直到str的长度达到len | +| RPAD(str,len,pad) | 用字符串pad对str最右边进行填充直到str的长度达到len | +| LTRIM(s) | 去掉字符串s左侧的空格 | +| RTRIM(s) | 去掉字符串s右侧的空格 | +| TRIM(s) | 去掉字符串s开始与结尾的空格 | +| TRIM([BOTH] s1 FROM s) | 去掉字符串s开始与结尾的s1 | +| TRIM([LEADING] s1 FROM s) | 去掉字符串s开始处的s1 | +| TRIM([TRAILING]s1 FROM s) | 去掉字符串s结尾处的s1 | +| INSERT(str,index,len,instr) | 将字符串str从index位置开始len个字符的替换为字符串instr | +| REPLACE(str,a,b) | 用字符串b替换字符串str中所有出现的字符串a | +| REPEAT(str,n) | 返回str重复n次的结果 | +| REVERSE(s) | 将字符串反转 | +| STRCMP(s1,s2) | 比较字符串s1,s2 | +| SUBSTRING(s,index,len) | 返回从字符串s的index位置截取len个字符 | +| SUBSTRING_INDEX(str, 分隔符,count) | 如果count是正数,那么从左往右数,第n个分隔符的左边的全部内容。例如,substring_index("www.mxdx.com",".",1)是"www"。如果count是负数,那么从右边开始数,第n个分隔符右边的所有内容。例如,substring_index("www.mxdx.com",".",-1)是"com"。 | + +##### 日期时间函数 + +| 函数 | 功能描述 | +| ------------------------------------------------------------ | --------------------------------------------------- | +| CURDATE()或CURRENT_DATE() | 返回当前系统日期 | +| CURTIME()或CURRENT_TIME() | 返回当前系统时间 | +| NOW()/SYSDATE()/CURRENT_TIMESTAMP()/ LOCALTIME()/LOCALTIMESTAMP() | 返回当前系统日期时间 | +| UTC_DATE()/UTC_TIME() | 返回当前UTC日期值/时间值 | +| UNIX_TIMESTAMP(date) | 返回一个UNIX时间戳 | +| YEAR(date)/MONTH(date)/DAY(date)/ HOUR(time)/MINUTE(time)/SECOND(time) | 返回具体的时间值 | +| EXTRACT(type FROM date) | 从日期中提取一部分值 | +| DAYOFMONTH(date)/DAYOFYEAR(date) | 返回一月/年中第几天 | +| WEEK(date)/WEEKOFYEAR(date) | 返回一年中的第几周 | +| DAYOFWEEK() | 返回周几,注意,周日是1,周一是2,…周六是7 | +| WEEKDAY(date) | 返回周几,注意,周一是0,周二是1,…周日是6 | +| DAYNAME(date) | 返回星期,MONDAY,TUESDAY,…SUNDAY | +| MONTHNAME(date) | 返回月份,January,… | +| DATEDIFF(date1,date2)/TIMEDIFF(time1,time2) | 返回date1-date2的日期间隔/返回time1-time2的时间间隔 | +| DATE_ADD(date,INTERVAL expr type)或ADDDATE/DATE_SUB/SUBDATE | 返回与给定日期相差INTERVAL时间段的日期 | +| ADDTIME(time,expr)/SUBTIME(time,expr) | 返回给定时间加上/减去expr的时间值 | +| DATE_FORMAT(datetime,fmt)/ TIME_FORMAT(time,fmt) | 按照字符串fmt格式化日期datetime值/时间time值 | +| STR_TO_DATE(str,fmt) | 按照字符串fmt对str进行解析,解析为一个日期 | +| GET_FORMAT(val_type,format_type) | 返回日期时间字符串的显示格式 | + +函数中日期时间类型说明 + +| 参数类型 | 描述 | 参数类型 | 描述 | +| -------- | ---- | ------------- | -------- | +| YEAR | 年 | YEAR_MONTH | 年月 | +| MONTH | 月 | DAY_HOUR | 日时 | +| DAY | 日 | DAY_MINUTE | 日时分 | +| HOUR | 时 | DAY_SECOND | 日时分秒 | +| MINUTE | 分 | HOUR_MINUTE | 时分 | +| SECOND | 秒 | HOUR_SECOND | 时分秒 | +| WEEK | 星期 | MINUTE_SECOND | 分秒 | +| QUARTER | 一刻 | | | + +函数中format参数说明 + +| 格式符 | 说明 | 格式符 | 说明 | +| ------ | --------------------------------------------------------- | ------ | ------------------------------------------------------- | +| %Y | 4位数字表示年份 | %y | 两位数字表示年份 | +| %M | 月名表示月份(January,…) | %m | 两位数字表示月份(01,02,03,…) | +| %b | 缩写的月名(Jan.,Feb.,…) | %c | 数字表示月份(1,2,3…) | +| %D | 英文后缀表示月中的天数(1st,2nd,3rd,…) | %d | 两位数字表示表示月中的天数(01,02,…) | +| %e | 数字形式表示月中的天数(1,2,3,…) | %p | AM或PM | +| %H | 两位数字表示小数,24小时制(01,02,03,…) | %h和%I | 两位数字表示小时,12小时制(01,02,03,…) | +| %k | 数字形式的小时,24小时制(1,2,3,…) | %l | 数字表示小时,12小时制(1,2,3,…) | +| %i | 两位数字表示分钟(00,01,02,…) | %S和%s | 两位数字表示秒(00,01,02,…) | +| %T | 时间,24小时制(hh:mm:ss) | %r | 时间,12小时制(hh:mm:ss)后加AM或PM | +| %W | 一周中的星期名称(Sunday,…) | %a | 一周中的星期缩写(Sun.,Mon.,Tues.,…) | +| %w | 以数字表示周中的天数(0=Sunday,1=Monday,…) | %j | 以3位数字表示年中的天数(001,002,…) | +| %U | 以数字表示的的第几周(1,2,3,…) 其中Sunday为周中的第一天 | %u | 以数字表示年中的年份(1,2,3,…) 其中Monday为周中第一天 | +| %V | 一年中第几周(01~53),周日为每周的第一天,和%X同时使用 | %X | 4位数形式表示该周的年份,周日为每周第一天,和%V同时使用 | +| %v | 一年中第几周(01~53),周一为每周的第一天,和%x同时使用 | %x | 4位数形式表示该周的年份,周一为每周第一天,和%v同时使用 | +| %% | 表示% | | | + +GET_FORMAT函数中val_type 和format_type参数说明 + +| 值类型 | 格式化类型 | 显示格式字符串 | +| -------- | ---------- | ----------------- | +| DATE | EUR | %d.%m.%Y | +| DATE | INTERVAL | %Y%m%d | +| DATE | ISO | %Y-%m-%d | +| DATE | JIS | %Y-%m-%d | +| DATE | USA | %m.%d.%Y | +| TIME | EUR | %H.%i.%s | +| TIME | INTERVAL | %H%i%s | +| TIME | ISO | %H:%i:%s | +| TIME | JIS | %H:%i:%s | +| TIME | USA | %h:%i:%s %p | +| DATETIME | EUR | %Y-%m-%d %H.%i.%s | +| DATETIME | INTERVAL | %Y%m%d %H%i%s | +| DATETIME | ISO | %Y-%m-%d %H:%i:%s | +| DATETIME | JIS | %Y-%m-%d %H:%i:%s | +| DATETIME | USA | %Y-%m-%d %H.%i.%s | + +#### 加密函数 + +| 函数 | 用法 | +| --------------------- | ------------------------------------------------------------ | +| password(str) | 返回字符串str的加密版本,41位长的字符串 | +| md5(str) | 返回字符串str的md5值,也是一种加密方式 | +| SHA(str) | 返回字符串str的sha算法加密字符串,40位十六进制值的密码字符串 | +| SHA2(str,hash_length) | 返回字符串str的sha算法加密字符串,密码字符串的长度是hash_length/4。hash_length可以是224、256、384、512、0,其中0等同于256。 | + +#### 条件判断 + +| 函数 | 功能 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| IF(value,t,f) | 如果value是真,返回t,否则返回f | +| IFNULL(value1,value2) | 如果value1不为空,返回value1,否则返回value2 | +| CASE WHEN 条件1 THEN result1 WHEN 条件2 THEN result2 … ELSE resultn END | 依次判断条件,哪个条件满足了,就返回对应的result,所有条件都不满足就返回ELSE的result。如果没有单独的ELSE子句,当所有WHEN后面的条件都不满足时则返回NULL值结果。等价于Java中if...else if.... | +| CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值2 THEN 值2 … ELSE 值n END | 判断表达式expr与哪个常量值匹配,找到匹配的就返回对应值,都不匹配就返回ELSE的值。如果没有单独的ELSE子句,当所有WHEN后面的常量值都不匹配时则返回NULL值结果。等价于Java中switch....case | + +#### 七种查询 + +###### (1)内连接 inner join + +###### (2)外连接 outer join + +左外连接 left outer join 或 left join + +右外连接 right outer join 或 right join + +全外连接 full outer join 或 full join -- union 代替 + +但是,mysql不支持全外连接,没有full join。 + +mysql使用union关键字合并其他的查询结果实现全外连接的效果。 + +内连接 ==> A∩B + +左连接 ==> A 或 A-A∩B + +右连接 ==> B 或 B-A∩B + +全外连接 ==> A∪B 或 A∪B - A∩B + +左连接的A union 右连接的B 得到 A∪B + +左连接的A-A∩B union 右连接B-A∩B 得到 A∪B - A∩B + +###### 使用union实现全外连接的效果 + +(1)A∪B + +转换为 左连接的A union 右连接的B + +(2)A∪B - A∩B + +转换为 左连接的A-A∩B union 右连接的B-A∩B + +###### 自连接 + +进行关联查询的两个表,本质上是一个表。 + +分析员工表: + +有一个字段是mid,是领导编号,即表示这个员工归谁管。 + +那么这里的领导编号其实就是这个领导他作为员工的员工编号。 + +通过取别名的方式,把一张表虚拟成两张表。 + +当然,也要关联字段。 + +# 作业 + +1. 设有一数据库,包括四个表:学生表(Student)、课程表(Course)、成绩表(Score)以及教师信息表(Teacher)。四个表的结构分别如表1-1的表(一)~表(四)所示,数据如表1-2的表(一)~表(四)所示。用SQL语句创建四个表并完成相关题目。 + +2. **数据库的表结构** + +表(一)Student (学生表) + +| 属性名 | 数据类型 | 可否为空 | 含义 | +| --------- | ------------ | -------- | ------------ | +| Sno | varchar (20) | 否 | 学号(主码) | +| Sname | varchar (20) | 否 | 学生姓名 | +| Ssex | varchar (20) | 否 | 学生性别 | +| Sbirthday | datetime | 可 | 学生出生年月 | +| Class | varchar (20) | 可 | 学生所在班级 | + +表(二)Course(课程表) + +| 属性名 | 数据类型 | 可否为空 | 含义 | +| ------ | ------------ | -------- | ---------------- | +| Cno | varchar (20) | 否 | 课程号(主码) | +| Cname | varchar (20) | 否 | 课程名称 | +| Tno | varchar (20) | 否 | 教工编号(外码) | + +表(三)Score(成绩表) + +| 属性名 | 数据类型 | 可否为空 | 含义 | +| -------------- | ------------ | -------- | -------------- | +| Sno | varchar (20) | 否 | 学号(外码) | +| Cno | varchar (20) | 否 | 课程号(外码) | +| Degree | Decimal(4,1) | 可 | 成绩 | +| 主码:Sno+ Cno | | | | + +表(四)Teacher(教师表) + +| 属性名 | 数据类型 | 可否为空 | 含义 | +| --------- | ------------ | -------- | ---------------- | +| Tno | varchar (20) | 否 | 教工编号(主码) | +| Tname | varchar (20) | 否 | 教工姓名 | +| Tsex | varchar (20) | 否 | 教工性别 | +| Tbirthday | datetime | 可 | 教工出生年月 | +| Prof | varchar (20) | 可 | 职称 | +| Depart | varchar (20) | 否 | 教工所在部门 | + +```mysql +create database test03 charset utf8; + +use test03; + +CREATE TABLE `student` ( + `Sno` varchar(20) NOT NULL COMMENT '学号', + `Sname` varchar(20) NOT NULL COMMENT '学生姓名', + `Ssex` varchar(20) NOT NULL COMMENT '学生性别', + `Sbirthday` datetime DEFAULT NULL COMMENT '学生出生年月', + `Class` varchar(20) DEFAULT NULL COMMENT '学生所在班级', + PRIMARY KEY (`Sno`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +insert into student values +('108','曾华','男','1977-9-1','95033'), +('105','匡明','男','1975-10-2','95031'), +('107','王丽','女','1976-1-23','95033'), +('101','李军','男','1976-2-20','95033'), +('109','王芳','女','1975-2-10','95031'), +('103','陆君','男','1974-6-3','95031'); + +CREATE TABLE `teacher` ( + `Tno` varchar(20) NOT NULL COMMENT '教工编号', + `Tname` varchar(20) NOT NULL COMMENT '教工姓名', + `Tsex` varchar(20) NOT NULL COMMENT '教工性别', + `Tbirthday` datetime DEFAULT NULL COMMENT '教工出生年月', + `Prof` varchar(20) DEFAULT NULL COMMENT '职称', + `Depart` varchar(20) NOT NULL COMMENT '教工所在部门', + PRIMARY KEY (`Tno`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +insert into teacher values +('804','李诚','男','1958-12-2','副教授','计算机系'), +('856','张旭','男','1969-3-12','讲师','电子工程系'), +('825','王萍','女','1972-5-5','助教','计算机系'), +('831','刘冰','女','1977-8-14','助教','电子工程系'); + +CREATE TABLE `course` ( + `Cno` varchar(20) NOT NULL COMMENT '课程号', + `Cname` varchar(20) NOT NULL COMMENT '课程名称', + `Tno` varchar(20) NOT NULL COMMENT '教工编号', + PRIMARY KEY (`Cno`), + KEY `Tno` (`Tno`), + CONSTRAINT `course_ibfk_1` FOREIGN KEY (`Tno`) REFERENCES `teacher` (`Tno`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +insert into course values +('3-105','计算机导论','825'), +('3-245','操作系统','804'), +('6-166','数字电路','856'), +('9-888','高等数学','831'); + +CREATE TABLE `score` ( + `Sno` varchar(20) NOT NULL COMMENT '学号', + `Cno` varchar(20) NOT NULL COMMENT '课程号', + `Degree` decimal(4,1) DEFAULT NULL COMMENT '成绩', + PRIMARY KEY (`Sno`,`Cno`), + KEY `Cno` (`Cno`), + CONSTRAINT `score_ibfk_1` FOREIGN KEY (`Cno`) REFERENCES `course` (`Cno`), + CONSTRAINT `score_ibfk_2` FOREIGN KEY (`Sno`) REFERENCES `student` (`Sno`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +insert into score values +('103','3-245',86), +('105','3-245',75), +('109','3-245',68), +('103','3-105',92), +('105','3-105',88), +('109','3-105',76), +('101','3-105',64), +('107','3-105',91), +('108','3-105',78), +('101','6-166',85), +('107','6-166',79), +('108','6-166',81); +``` + +3. **数据库中的数据**: + +-- 1,查询所有学生,都学了哪些课程,要显示学生信息和课程信息 + +```mysql +select sname,course.cname from student inner join score on student.sno=score.sno left join course on score.cno=course.cno; +``` + +-- 2,查询没有学生的教师的所有信息 + +表(一)Student + +| Sno | Sname | Ssex | Sbirthday | class | +| ---- | ----- | ---- | --------- | ----- | +| 108 | 曾华 | 男 | 1977-9-1 | 95033 | +| 105 | 匡明 | 男 | 1975-10-2 | 95031 | +| 107 | 王丽 | 女 | 1976-1-23 | 95033 | +| 101 | 李军 | 男 | 1976-2-20 | 95033 | +| 109 | 王芳 | 女 | 1975-2-10 | 95031 | +| 103 | 陆君 | 男 | 1974-6-3 | 95031 | + +表(二)Course + +| Cno | Cname | Tno | +| ----- | ---------- | ---- | +| 3-105 | 计算机导论 | 825 | +| 3-245 | 操作系统 | 804 | +| 6-166 | 数字电路 | 856 | +| 9-888 | 高等数学 | 831 | + +表(三)Score + +| Sno | Cno | Degree | +| ---- | ----- | ------ | +| 103 | 3-245 | 86 | +| 105 | 3-245 | 75 | +| 109 | 3-245 | 68 | +| 103 | 3-105 | 92 | +| 105 | 3-105 | 88 | +| 109 | 3-105 | 76 | +| 101 | 3-105 | 64 | +| 107 | 3-105 | 91 | +| 108 | 3-105 | 78 | +| 101 | 6-166 | 85 | +| 107 | 6-166 | 79 | +| 108 | 6-166 | 81 | + +表(四)Teacher + +| Tno | Tname | Tsex | Tbirthday | Prof | Depart | +| ---- | ----- | ---- | --------- | ------ | ---------- | +| 804 | 李诚 | 男 | 1958-12-2 | 副教授 | 计算机系 | +| 856 | 张旭 | 男 | 1969-3-12 | 讲师 | 电子工程系 | +| 825 | 王萍 | 女 | 1972-5-5 | 助教 | 计算机系 | +| 831 | 刘冰 | 女 | 1977-8-14 | 助教 | 电子工程系 | + +3. **数据库中的数据**: + +-- 1,查询所有学生,都学了哪些课程,要显示学生信息和课程信息 + +```mysql +select sname,course.cname from student inner join score on student.sno=score.sno left join course on score.cno=course.cno; +``` + +-- 2,查询没有学生的教师的所有信息 + +```mysql +select Teacher.Tno,Tname,Tsex,Tbirthday,Prof,Depart from Teacher left join Course on Teacher.Tno = Course.Tno left join Score on Course.Cno = Score.Cno where Score.Sno is null; +``` + +4. ##### 查询: + +① 查询Score表中的最高分的学生学号和课程号。 + +```mysql +select sno,cno from score where degree=(select max(degree) from score); +``` + +② 查询所有学生的Sname、Cno和Degree列。 + +```mysql +select Sname,Cno,Degree from Student,Score where Student.Sno=Score.Sno; +``` + +③ 查询所有学生的Sno、Cname和Degree列。 + +```mysql +select sno,cname,degree from course,score where course.cno = score.cno; +``` + +④ 查询所有学生的Sname、Cname和Degree列。 + +```mysql +select sname,cname,degree from student,course,score where student.sno=score.sno and course.cno=score.cno; +``` + +⑤ 查询“95033”班学生的平均分。 + +```mysql +select cno,avg(degree) from score where sno in (select sno from student where class='95031') group by cno; +``` + +⑥ 查询选修“3-105”课程的成绩高于“109”号同学成绩的所有同学的记录。 + +```mysql +select * from score where cno='3-105' and degree>(select degree from score where sno='109' and cno='3-105'); +``` + +⑦ 查询score中选学多门课程的同学中分数为非最高分成绩的记录。 + +```mysql +select * from Score a where Degree <(select MAX(degree) from Score b where a.Cno=b.Cno) and Sno in(select Sno from Score group by Sno having count(*)>1); +``` + +⑧ 查询成绩高于学号为“109”、课程号为“3-105”的成绩的所有记录。 + +```mysql +select * from Student,Score where Student.Sno=Score.Sno and Score.Degree>(select Degree from Score where Cno='3-105' and Sno='109'); +``` + +⑨ 查询和学号为108的同学同年出生的所有学生的Sno、Sname和Sbirthday列。 + +```mysql +select sno,sname,sbirthday from student where sbirthday in (select sbirthday from student where sno='108'); +``` + +⑩ 查询“张旭“教师任课的学生成绩。 + +```mysql +select Sname,Degree from Student,Score where Student.Sno=Score.Sno and Cno ='6-166'; +``` + +11 查询选修某课程的同学人数多于5人的教师姓名。 + +```mysql +Select * from teacher where tno=(Select tno from course where cno=(Select cno from score group by cno having count(*)>5)); +``` + +12 查询出“计算机系“教师所教课程的成绩表。 + +```mysql +select * from score where cno in(select cno from course where tno in(select tno from teacher where depart='计算机系')); +``` + +13 查询“计算机系”与“电子工程系“不同职称的教师的Tname和Prof。 + +```mysql +select Tname,Prof from Teacher a where Prof not in(select Prof from Teacher b where a.Depart!=b.Depart); +``` + +14 查询选修编号为“3-105“课程且成绩至少高于选修编号为“3-245”的同学的Cno、Sno和Degree,并按Degree从高到低次序排序。 + +```mysql +select * from score where cno='3-105' and degree>any(select degree from score where cno='3-245') order by degree desc; +``` + +15 查询选修编号为“3-105”且成绩高于选修编号为“3-245”课程的同学的Cno、Sno和Degree. + +```mysql +select * from score where cno='3-105' and degree>all(select degree from score where cno='3-245'); +``` + +16 查询成绩比该课程平均成绩低的同学的成绩表。 + +```mysql +select Sno,Cno,Degree from Score a where a.Degree<(select AVG(Degree) from Score b where a.Cno=b.Cno); +``` + +17 查询所有任课教师的Tname和Depart. + +```mysql +select Tname,Depart from Teacher where Tname in (select distinct Tname from Teacher,Course,Score where Teacher.Tno=Course.Tno and Course.Cno=Score.Cno); +``` + +18 查询所有未讲课的教师的Tname和Depart. + +```mysql +select Tname,Depart from Teacher where Tname not in (select distinct Tname from Teacher,Course,Score where Teacher.Tno=Course.Tno and Course.Cno=Score.Cno); +``` + +19 查询“男”教师及其所上的课程。 + +```mysql +select Tname,Cname from Teacher,Course where Tsex='男' and Teacher.Tno=Course.Tno; +``` + +20 查询最高分同学的Sno、Cno和Degree列。 + +```mysql +select sno,cno,degree from score where degree = (select max(degree) from score); +``` + +21 查询和“李军”同性别的所有同学的Sname. + +```mysql +select sname from student where ssex = (select ssex from student where sname = '李军'); +``` + +22 查询和“李军”同性别并同班的同学Sname. + +```mysql +select sname from student where ssex = (select ssex from student where sname = '李军') and class = (select class from student where sname = '李军'); +``` + +23 查询所有选修“计算机导论”课程的“男”同学的成绩表。 + +```mysql +select sname,ssex,degree from student s,course c,score sc where s.sno=sc.sno and sc.cno=c.cno and c.cname = '计算机导论' and s.ssex = '男'; +``` +