数据查询 SELECT
SELECT 查找的列
FROM 表
WHERE 查找条件
(一般前三行就够了)
GROUP BY 列名(分组查询)
HAVING 条件
ORDER BY 列名 ASC/DESC 升序(默认)/降序
假设数据库中有四个表:
T(T_id, TNAME, TITLE)
C(C_id, CNAME, T_id)
S(S_id, SNAME, AGE, SEX)
SC(S_id, C_id, SCORE)
SELECT:
1.* 返回元组(记录)的所有列
列出S表中所有男生的信息
SELECT *
FROM S
WHERE SEX='M';
2.ALL/DISTINCT 全部显示(默认)/消除重复项目
列出学生姓名,去除重复项
SELECT DISTINCT SNAME 消除重复的学生名
FROM S;
3.COUNT(*) 计算元组(记录)的条数、COUNT(列名) 计算列中的有值的行的个数、SUM(列名)、AVG(列名)、MAX(列名)、MIN(列名)
列出S表中男生的人数,年龄平均值
SELECT COUNT(*),AVG(AGE)
FROM S
WHERE SEX='M';
4.LOWER(列名)/UPPER(列名),将列的内容小写/大写
5.ROUND 四舍五入、TRUNC 取整、MOD 取余等函数
WHERE:
1.>、=等比较运算符,<>和!=表示不等于
列出年龄大于18的学生姓名
SELECT SNAME
FROM S
WHERE AGE>18;
2.AND、OR、NOT逻辑运算符
列出年龄大于18的男生姓名
SELECT SNAME
FROM S
WHERE AGE>18 AND SEX='M';
3.IN、NOT IN
列出年龄是18、19的学生姓名
SELECT SNAME
FROM S
WHERE AGE IN (18,19);
4.BETWEEN … AND/NOT BETWEEN AND
(同上)列出年龄是18、19的学生姓名
SELECT SNAME
FROM S
WHERE AGE BETWEEN 18 AND 19;
5.IS NULL 查看某一项是否为空
6.LIKE 匹配类似字符串
_ 代表单字,% 代表零个或多个字
a%b_: a开头,倒数第二个字是b的字符串
找到名字最后一个字是k的学生。
SELECT SNAME
FROM S
WHERE SNAME LIKE '%k';
7.|| 连接两个列,不留空格
将学生学号和姓名一起列出
SELECT S_id|| SNAME
FROM S;
8.连接相关:=
内连接:两个表一 一对应,表1中的某项不会找不到对应
找出Morty所选课程的编号
SELECT C_id
FROM S,SC
WHERE S.S_id=SC.S_id AND SNAME='Morty'; 将两个表建立连接,通过共有的列
如果是3个表,就需要2个连接,4个表就要3个连接。
外连接:两个表不是一 一对应,可能表1中的某些元组没有对应
列出S和SC中的S_id
假设SC中还有几个学生的编号没写入
SELECT S.S_id,SC.S_id
FROM S,SC
WHERE S.S_id=SC.S_id(+);
那么结果会是,S中所有的S_id都输出了,而SC中有几条S_id是空值NULL。
用JOIN、USING等也可以(这里没细讲,书上95页有)
SELECT e.employee_id, e.last_name, d.location_id
FROM employees e JOIN departments d
USING (department_id);
上下这两个,都是e、d两个表根据department_id连接
SELECT e.employee_id, e.last_name, e.department_id,
d.department_id, d.location_id
FROM employees e JOIN departments d
ON (e.department_id = d.department_id);
9.嵌套相关:IN、NOT IN、EXISTS、NOT EXISTS、UNIQUE
不相关子查询
内查询 不需要 用 外查询的表
只执行一遍内查询
找到选择课程C2的学生和学号
SELECT S_id,SNAME
FROM S
WHERE S_id IN(SELECT S_id
FROM SC
WHERE C_id='C2');
先执行内查询,找到SC中C2课程的所有学生的学号,得到一个学号的表
再执行外查询,找到学号在刚刚学号表里的学生
相关子查询
内查询 需要 用 外查询的表
IN
找到选择课程C2的学生和学号
SELECT S_id,SNAME
FROM S
WHERE 'C2' IN(SELECT C_id
FROM SC
WHERE SC.S_id=S.S_id);
类似for语句,先执行外查询,对S中的每一行,都执行一遍内查询
比如,当外查询查到学生S1时,内查询就变成:
SELECT C_id
FROM SC
WHERE SC.S_id=S1;
内查询就得到S1所选的所有课程的编号,如果C2在这些编号里,S1就被选中。
接下来查S2,再次进行内查询:
SELECT C_id
FROM SC
WHERE SC.S_id=S2;
......
外查询有多少个元组,有多少个学生,内查询就要执行多少次
EXISTS(SELECT …) 如果内查询 SELECT 的结果为非空,EXISTS 返回真;结果为空,EXISTS 返回假
SELECT S_id,SNAME
FROM S
WHERE EXISTS(SELECT *
FROM SC
WHERE SC.S_id=S.S_id AND C_id='C2');
和上面类似,这里也像for一样,先执行外查询,对每一个学生,都执行一遍内查询,查到S1时,内查询变为:
SELECT *
FROM SC
WHERE SC.S_id=S1 AND C_id='C2';查到S1学生选课程C2的记录,如果S1没选C2时,结果就为空。外查询再根据查询结果是否为空,来决定是否选S1。
下面再把S2代入内查询......
外查询有多少个元组,内查询就要执行多少次
GROUP BY:
(有WHERE的话)GROUP BY (列名) 将 WHERE 找到的多行记录分组,分组依据是列名
然后 SELECT 按组输出,每组输出一行
SELECT department_id, AVG(salary)
FROM employees
GROUP BY department_id; 将员工按部门分组,输出每部门的平均工资
SELECT department_id, job_id, SUM(salary)
FROM employees
GROUP BY department_id, job_id ; 先将员工按部门分组,再按工作种类分组,输出同一部门中同一工作的工资总和
HAVING:
只可以在 GROUP BY 之后使用,对 GROUP BY 得到的各个分组进行筛选。
SELECT department_id, MAX(salary)
FROM employees
GROUP BY department_id 按部门号分组
HAVING MAX(salary)>10000; 将部门内最高工资>10000的部门留下,其他的去掉
ORDER BY:
ORDER BY 列名(排序依据) ASC/DESC 升序(默认)/降序
ORDER BY AGE DESC;
其他的:
起别名
在 SELECT 和 FROM 中,都可以在 表和列 后加 AS(可以省略),再加新名字
SELECT COUNT(*) "Number of Managers" 如果不是空格断开的字符串,就不需要双引号
...
集合的并、交、差:
UNION 、INTERSECT、EXCEPT
将两个查询结果做并、交、差。
SELECT ...
FROM ...
WHERE ...
UNION
SELECT ...
FROM ...
WHERE ...
建议还是多做练习理解,如书上83、84、85页

4万+

被折叠的 条评论
为什么被折叠?



