查看数据库字符集:
SHOW GLOBAL VARIABLES LIKE '%character_set%';
1.加入关键字distinct ,去除重复
SELECT DISTINCT dept_name
FROM instructor;
2 . 找到在Comp. Sci. 系且工资>70000的老师名字:
(系名称直接从表内粘,注意空格)
SELECT `name`
FROM instructor
WHERE dept_name = 'Comp. Sci.' AND salary > 70000;
1 . dept_name 属性在instructor,department内都有,选择时必须指定关系表
SELECT `name`,instructor.dept_name,building
FROM instructor,department
WHERE instructor.dept_name = department.dept_name;
2 . 笛卡儿积:结果产生所有组合
SELECT `name`,course_id
FROM instructor,teaches;
3 . where 限制笛卡儿积建立的组合
SELECT `name`,course_id
FROM instructor,teaches
WHERE instructor.ID = teaches.ID;
4 . 自然连接:筛选出在两个关系表中都出现的属性上取值相同的元组对
上面语句可以修改为:
SELECT `name`,course_id
FROM instructor NATURAL JOIN teaches;
5 .列出老师名字和所教授的课程名称
instructor 与 teaches自然连接结果,再与course作笛卡儿积
SELECT `name`,title
FROM instructor NATURAL JOIN teaches,course
WHERE teaches.course_id = course.course_id;
6 .上面语句用 r1 join r2 using(A1,A2):
等价于 t1.A1 = t2.A1 and t1.A2 = t2.A2
SELECT `name`,title
FROM (instructor NATURAL JOIN teaches) JOIN course USING (course_id);
7 .表别名(相关变量)
找出满足下面条件的老师名字,他们比Biology 系老师的最低工资要高:
(where 子句中不能用instructor.salary 这里T、S都是instructor的别名)
SELECT DISTINCT T.`name`
FROM instructor AS T ,instructor AS S
WHERE T.salary > S.salary AND S.dept_name = 'Biology';
desc(降序)、asc(升序)
按salary降序排列instructor,若薪资相同,再按name升序排列
SELECT *
FROM instructor
ORDER BY salary DESC , `name` ASC;
(a1,b1) <= (a2,b2) 在a1 <= a2 且 b1 <= b2时为真
SELECT `name`,course_id
FROM instructor,teaches
WHERE (instructor.ID,dept_name) = (teaches.ID,'biology');
上面语句等价于:
SELECT `name`,course_id
FROM instructor,teaches
WHERE instructor.ID = teaches.ID AND dept_name= 'biology';
union (并),优势:union运算结果自动去除重复
若想保留重复,用 union all
代码中()可省略,但加上便于阅读
(SELECT course_id
FROM section
WHERE semester = 'fall' AND `year` = 2009)
UNION
(SELECT course_id
FROM section
WHERE semester = 'spring' AND `year` = 2010);
intersect(交),mysql不支持intersect运算,用 inner join 表示交:
找出在2009年秋季和2010年春季学期同时开课的所有课程:
方法一:(intersect, mysql不支持)
(SELECT course_id
FROM section
WHERE semester = 'fall' AND `year` = 2009)
intersect
(SELECT course_id
FROM section
WHERE semester = 'spring' AND `year` = 2010);
方法二:(INNER JOIN)
SELECT DISTINCT a.course_id FROM
(SELECT course_id
FROM section
WHERE semester = 'fall' AND `year` = 2009) a
INNER JOIN
(SELECT course_id
FROM section
WHERE semester = 'spring' AND `year` = 2010) b
ON (a.course_id = b.course_id);
注意:intersect 自动去除重复,intersect all 保留重复
inner join不能自动去除重复,可用select distinct 去除重复结果
方法三:还可以用in测试元组是否是集合中的成员
(where子句嵌套子查询)
SELECT DISTINCT course_id
from section
where semester = 'fall' and `year` = 2009 and
course_id in (SELECT course_id
from section
where semester = 'spring' and `year` = 2010);
except(差),mysql不支持except运算,用not in 或者 not exists,
not exists支持NULL值
找出所有在2009年秋季学期开课,但不在2010年春季学期开课的课程:
方法一:(except, mysql不支持)
(SELECT course_id
FROM section
WHERE semester = 'fall' AND `year` = 2009)
except
(SELECT course_id
FROM section
WHERE semester = 'spring' AND `year` = 2010);
方法二:mysql用not exists 或者not in:
select course_id
from section sf
where semester = 'Fall' and year = 2009 and not exists
(select course_id
from section ss
where sf.course_id = ss.course_id and ss.semester = 'Spring' and ss.year = 2010
);
更简单的代码:(select distinct 删除重复)
select distinct course_id
from section
where course_id not in
(
select course_id
from section
where semester = 'Spring' and year= 2010
)
and semester = 'Fall' and year = 2009;
SELECT DISTINCT course_id
from section
where semester = 'fall' and `year` = 2009 and
course_id not in (SELECT course_id
from section
where semester = 'spring' and `year` = 2010);
count(计数) :
1 .找出在2010年春季学期讲授一门课程的老师的总数。
( 不论这个老师讲了几门课,都计为一次)
用 distinct ID确定唯一的老师ID号:
SELECT COUNT(DISTINCT ID)
FROM teaches
WHERE semester = 'spring' AND `year` = 2010;
2 .(题目难) 找出每个系在2010年春季学期讲授一门课程的老师人数。
同样用 distinct ID来确定唯一的老师ID号,这里teaches关系表需要关联 instructor关系表中的属性(系名称dept_name),用nature join 自然连接筛选出两个关系表中共同的ID,代码:
SELECT dept_name,COUNT(DISTINCT ID) AS instr_count
FROM instructor natural join teaches
WHERE semester = 'spring' and `year` = 2010
GROUP BY dept_name;
having子句中的谓词在形成分组后才起作用,即在group by子句后
找出教师平均工资超过42000美元的系名字,按系名分组
SELECT dept_name,AVG(salary) as avg_salary
FROM instructor
GROUP BY dept_name
HAVING AVG(salary) > 42000;
1 .至少比一个要大,用 > some表示
找出比biology系某一个老师的工资要高的所有老师名字:
方法一:
SELECT DISTINCT T.`name`
FROM instructor AS T,instructor AS S
WHERE T.salary > S.salary AND S.dept_name = 'biology';
方法二:至少比一个要大,用 > some表示
SELECT `name`
FROM instructor
WHERE salary > SOME (SELECT salary
FROM instructor
WHERE dept_name = 'biology');
2 . 比所有的都大,用 > all 表示
找出比biology系每一个老师的工资要高的所有老师名字:
SELECT `name`
FROM instructor
WHERE salary > ALL (SELECT salary
FROM instructor
WHERE dept_name = 'biology');
3 . 找出平均工资最高的系
step1: 找出每个系的平均工资
step2: 找出平均工资大于等于所有系平均工资的系(用 >= all)
step1:
SELECT AVG(salary)
FROM instructor
GROUP BY dept_name
step2:
SELECT dept_name
FROM instructor
GROUP BY dept_name
HAVING AVG(salary) >= ALL(SELECT AVG(salary)
FROM instructor
GROUP BY dept_name);
3.7.3的问题另解:找出教师平均工资超过42000美元的系名字,按系名分组(用select-from-where 嵌套查询):
SELECT dept_name,avg_salary
from (SELECT dept_name,AVG(salary) as avg_salary
from instructor
GROUP BY dept_name) b
WHERE avg_salary > 42000;
注意这里 子查询里用 b 作为表别名,必须每个表都有名
select * from (select * from ……) as 别名;
with子句定义临时关系,这个定义只对包含with子句的查询有效。
1 . 找出具有最大预算值的系:
with max_budget(VALUE) as
(SELECT max(budget)
from department)
SELECT budget
from department,max_budget
where department.budget = max_budget.value;
2 . 找出所有工资总额大于所有系平均工资总额的系:
(难)
with dept_total(dept_name,value) as
(SELECT dept_name,sum(salary)
from instructor
GROUP BY dept_name),
dept_total_avg(value) as
(SELECT avg(value)
from dept_total)
SELECT dept_name
from dept_total,dept_total_avg
where dept_total.value >= dept_total_avg.value;
子查询可以放在任何位置,只要该子查询只返回包含单个属性的单个元组。
列出所有的系及它们拥有的老师数:
SELECT dept_name,
(SELECT COUNT(*)
from instructor
WHERE department.dept_name = instructor.dept_name)
as num_instructors
FROM department;
这里 dept_name , (老师数)num_instructors 都是属性
delete from 关系表 # 删除表中的所有元组,关系表仍然存在
从instructor关系中删除所有这样的教师元组,他们位于Watson大楼的系工作:
DELETE FROM instructor
WHERE dept_name IN(SELECT dept_name
FROM department
WHERE building = 'Watson');
首先找到Watson大楼的系,再将这些系里的instructor元组全部删除。
给工资超过100000的老师涨3%的工资,其余老师涨5%:
方法一:(update 注意语序)
UPDATE instructor
SET salary = salary * 1.03
WHERE salary > 100000;
UPDATE instructor
SET salary = salary * 1.05
WHERE salary <= 100000;
注意:如果改变UPDATE 语序,工资略低于100000的老师工资将涨8%,更新顺序很重要。
方法二:(case 避免了语序更新问题)
UPDATE instructor
SET salary = case
WHEN salary <= 100000 THEN salary * 1.05
ELSE salary * 1.03
END
1 . 删:delete from 关系表
2 . 增:insert into 关系表
insert into 关系表
values()
3 .改:
update 关系表
set 属性 = XXX
e. 找出2009年秋季开设的每个课程段的选课人数
SELECT course_id,sec_id,COUNT(ID)
FROM takes NATURAL JOIN section
WHERE `year` = 2009 AND semester = 'fall'
GROUP BY course_id,sec_id;
f. 从2009年秋季开设的所有课程中,找出最多的选课人数
SELECT MAX(enrollment)
FROM (SELECT COUNT(ID) as enrollment
FROM takes NATURAL JOIN section
WHERE `year` = 2009 AND semester = 'fall'
GROUP BY course_id,sec_id) b;
g.找出在2009年秋季拥有最多选课人数的课程数
WITH sec_enrollment AS (
SELECT course_id,sec_id, count(ID) as enrollment
FROM takes NATURAL JOIN section
WHERE `year` = 2009 AND semester = 'fall'
GROUP BY course_id,sec_id)
SELECT course_id,sec_id
FROM sec_enrollment
WHERE enrollment = (SELECT max(enrollment) from sec_enrollment);