User-Defined Variables
1 mysql> SET @w := SELECT COUNT(*) FROM course WHERE cteacher='程军'; 2 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version 3 the right syntax to use near 'SELECT COUNT(*) FROM course WHERE cteacher='程军'' at line 1 4 mysql> SELECT @w; 5 +------+ 6 | @w | 7 +------+ 8 | NULL | 9 +------+ 10 1 row in set (0.00 sec) 11 12 mysql> SET @w := (SELECT COUNT(*) FROM course WHERE cteacher='程军'); 13 Query OK, 0 rows affected (0.00 sec) 14 15 mysql> SELECT @w; 16 +------+ 17 | @w | 18 +------+ 19 | 2 | 20 +------+ 21 1 row in set (0.00 sec) 22 23 mysql>
1 SHOW TABLES; 2 DROP TABLE IF EXISTS student; 3 SHOW TABLES; 4 CREATE TABLE IF NOT EXISTS student 5 ( 6 sno int primary key, 7 sname VARCHAR(20) CHARACTER SET gbk, 8 sage TINYINT, 9 shair ENUM('黑','白') CHARACTER SET gbk 10 ); 11 INSERT INTO student VALUES('1','李强',23,'黑'); 12 INSERT INTO student VALUES('2','刘丽',22,'白'); 13 INSERT INTO student VALUES('5','张友',22,'黑'); 14 SELECT * FROM student; 15 16 SHOW TABLES; 17 DROP TABLE IF EXISTS course; 18 SHOW TABLES; 19 CREATE TABLE IF NOT EXISTS course 20 ( 21 cno VARCHAR(10) primary key, 22 cname VARCHAR(20) CHARACTER SET gbk, 23 cteacher VARCHAR(20) CHARACTER SET gbk 24 ); 25 INSERT INTO course VALUES('k1','c语言','王华'); 26 INSERT INTO course VALUES('k5','数据库原理','程军'); 27 INSERT INTO course VALUES('k8','编译原理','程军'); 28 SELECT * FROM course; 29 30 SHOW TABLES; 31 DROP TABLE IF EXISTS sc; 32 SHOW TABLES; 33 CREATE TABLE IF NOT EXISTS sc 34 ( 35 fk_sno INT NOT NULL, 36 fk_cno VARCHAR(10) NOT NULL, 37 score INT NOT NULL, 38 PRIMARY KEY(fk_sno,fk_cno), 39 FOREIGN KEY(fk_sno) REFERENCES student(sno), 40 FOREIGN KEY(fk_cno) REFERENCES course(cno) 41 ); 42 INSERT INTO sc VALUES('1','K1',83); 43 INSERT INTO sc VALUES('2','K1',85); 44 INSERT INTO sc VALUES('5','K1',92); 45 INSERT INTO sc VALUES('2','K5',90); 46 INSERT INTO sc VALUES('5','K5',84); 47 INSERT INTO sc VALUES('5','K8',80); 48 SELECT * FROM sc;
1-检索至少选修"程军"老师所授全部课程的学生姓名(SNAME)
检索选修了“程军”老师所授全部课程的学生姓名
0-检索选修了“程军”老师所授课程的学生
1 SELECT * FROM sc RIGHT JOIN course ON sc.fk_cno=course.cno; 2 SELECT * FROM (SELECT * FROM sc RIGHT JOIN course ON sc.fk_cno=course.cno) w RIGHT JOIN student ON w.fk_sno=student.sno; 3 SELECT * FROM (SELECT * FROM sc RIGHT JOIN course ON sc.fk_cno=course.cno) w RIGHT JOIN student ON w.fk_sno=student.sno WHERE cteacher='程军';
集合子集,逐步精确,缩小范围 1-是学生-2-选程老师的课-3-选了程老师所有的课
/*
假定
“ 某学生选程老师的课程门数等于程老师所开门数”等价于“该学生至少选了程老师的所有的课程”。
*/
1 SELECT sname FROM student 2 WHERE 3 ( 4 SELECT COUNT(*) FROM 5 ( 6 SELECT * FROM (SELECT * FROM sc RIGHT JOIN course ON sc.fk_cno=course.cno) w RIGHT JOIN student ON w.fk_sno=student.sno 7 WHERE cteacher = '程军' 8 ) wb 9 WHERE wb.sname = student.sname 10 ) 11 = 12 (SELECT COUNT(*) FROM course WHERE cteacher='程军');
/* 0-澄清问题:找出至少选了程老师全部课程的学生:学生-没有选程老师的课+学生选了程老师的部分的课+学生选了程老师全部的课
等价转化:找出选了程老师部分的课或者没有选程老师的课的学生
数据关系:学生和老师没有数据关系,是两个完全独立的数据对象,分数是桥梁
等价转化:
选了部分程老师的课 ,NOT EXISTS (SELECT * FROM sc WHERE sc.sno = student AND sc.cno=course.cno)->FALSE (内层SELECT不空,TRUE,退出)
没有选程老师的课 teacher='程军'->FALSE ,后边的不用看了(中层SELECT空,FALSE,退出)
外中内-三层SELECT,外层返回的是最终的结果
最外层选得的最终量result,学生姓名,它的措施是将各个学生名称带入,逐个检测
1-程序表达: */
1 SELECT sname FROM student 2 WHERE NOT EXISTS 3 ( 4 SELECT * FROM course 5 WHERE cteacher='程军' AND NOT EXISTS 6 ( 7 SELECT * FROM sc 8 WHERE sc.fk_sno = student.sno AND sc.fk_cno = course.cno 9 ) 10 ) ;
2- 检索选修全部课程的学生姓名(SNAME)。
1 SELECT sname FROM student 2 WHERE 3 ( 4 SELECT COUNT(*) FROM 5 ( 6 SELECT * FROM (SELECT * FROM sc RIGHT JOIN course ON sc.fk_cno=course.cno) w RIGHT JOIN student ON w.fk_sno=student.sno 7 ) wb 8 WHERE wb.sname = student.sname 9 ) 10 = 11 (SELECT COUNT(*) FROM course ); 12 13 SELECT sname FROM student 14 WHERE NOT EXISTS 15 ( 16 SELECT * FROM course 17 WHERE NOT EXISTS 18 ( 19 SELECT * FROM sc 20 WHERE sc.fk_sno = student.sno AND sc.fk_cno = course.cno 21 ) 22 ); 23 24 SELECT * FROM course 25 WHERE NOT EXISTS 26 ( 27 SELECT 3>5 28 ); 29 30 SELECT * FROM course 31 WHERE EXISTS 32 ( 33 SELECT 3>5 34 );
explain
1 mysql> explain 2 -> SELECT sname FROM student 3 -> WHERE 4 -> ( 5 -> SELECT COUNT(*) FROM 6 -> ( 7 -> SELECT * FROM (SELECT * FROM sc RIGHT JOIN course ON sc.fk_cno=course.cno) w RIGHT JOIN student ON w.fk_sno=student.sno 8 -> ) wb 9 -> WHERE wb.sname = student.sname 10 -> ) 11 -> = 12 -> (SELECT COUNT(*) FROM course ); 13 +----+--------------------+---------+------------+--------+----------------+---------+---------+-------------------+------+----------+------------------------------+ 14 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 15 +----+--------------------+---------+------------+--------+----------------+---------+---------+-------------------+------+----------+------------------------------+ 16 | 1 | PRIMARY | student | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | Using where | 17 | 5 | SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away | 18 | 2 | DEPENDENT SUBQUERY | student | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where | 19 | 2 | DEPENDENT SUBQUERY | sc | NULL | ref | PRIMARY,fk_cno | PRIMARY | 4 | w0811.student.sno | 2 | 100.00 | Using index | 20 | 2 | DEPENDENT SUBQUERY | course | NULL | eq_ref | PRIMARY | PRIMARY | 12 | w0811.sc.fk_cno | 1 | 100.00 | Using index | 21 +----+--------------------+---------+------------+--------+----------------+---------+---------+-------------------+------+----------+------------------------------+ 22 5 rows in set, 2 warnings (0.00 sec) 23 24 mysql> 25 mysql> explain 26 -> SELECT sname FROM student 27 -> WHERE NOT EXISTS 28 -> ( 29 -> SELECT * FROM course 30 -> WHERE NOT EXISTS 31 -> ( 32 -> SELECT * FROM sc 33 -> WHERE sc.fk_sno = student.sno AND sc.fk_cno = course.cno 34 -> ) 35 -> ); 36 +----+--------------------+---------+------------+--------+----------------+---------+---------+------------------------------------+------+----------+--------------------------+ 37 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 38 +----+--------------------+---------+------------+--------+----------------+---------+---------+------------------------------------+------+----------+--------------------------+ 39 | 1 | PRIMARY | student | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | Using where | 40 | 2 | DEPENDENT SUBQUERY | course | NULL | index | NULL | PRIMARY | 12 | NULL | 3 | 100.00 | Using where; Using index | 41 | 3 | DEPENDENT SUBQUERY | sc | NULL | eq_ref | PRIMARY,fk_cno | PRIMARY | 16 | w0811.student.sno,w0811.course.cno | 1 | 100.00 | Using index | 42 +----+--------------------+---------+------------+--------+----------------+---------+---------+------------------------------------+------+----------+--------------------------+ 43 3 rows in set, 3 warnings (0.00 sec) 44 45 mysql>
“带入遍历”,“重复循环”,这是上边代码原貌,而两种思路的区别仅仅是让计算机计算时怎样“重复次数”少一点。
http://blog.csdn.net/wolfofsiberian/article/details/39346781
发问:
0-语言只是工具而已,不是解决问题方法的源泉,怎么减少对接语法API的时间?