本文为《SQL学习指南》一书的学习笔记,供自己记录查找使用。如有侵权可私信删除.
今日文章包括:chap 3 SELECT查询入门;chap 4 过滤;chap 5 多表连接。
目录
一、select子句
在select子句中可以使用列名、字符、表达式和内建函数。
SELECT emp_id,
-> 'ACTIVE',
-> emp_id * 3.14159,
-> UPPER(lname)
-> FROM employee;
如果只是需要执行一个内建函数 or 对表达式求值,则不需要调用任何表,可以不使用FROM子句。例如:
SELECT VERSION(),
-> USER(),
-> DATABASE();
1.列的别名(标签)
select column_1 as label_1,column_2 as label_2,… ,as可以省略,即
select column_1 label_1,column_2 label_2,…
SELECT emp_id,
-> 'ACTIVE' status,
-> emp_id * 3.14159 empid_x_pi,
-> UPPER(lname) last_name_upper
-> FROM employee;
2.去除重复值
使用DISTINCT关键字 (系统默认不去除:ALL)
二、FROM子句
定义所查询的表以及他们的连接方式。有三种表:
- 永久表 (create table语句所创建)
- 临时表 (子查询所返回的表)
- 虚拟表 (create view 所创建的视图)
1.虚拟表(视图)
视图又叫虚拟表,表现得象一个表但实际上并不具有任何数据,它是存储在数据字典中的查询。通常用于对用户隐藏列、简化数据库设计等场景。
示例:
CREATE VIEW employee_vw AS
-> SELECT emp_id,fname,lname,
-> YEAR(start_date) start_year
-> FROM employee;
创建了视图之后并没有产生或存储任何数据,只是简单保留了这个查询以供后续使用。比如现在可以查询这个视图:
SELECT emp_id,start_year
-> FROM employee_vw;
2.两表连接
可以使用多种JOIN语句对表进行连接。
内连接 INNER JOIN
是默认的连接方式。如果连接两表的列中的某一条数据在其中一个表中不存在,内连接所得的新表将不包含这条数据。这是默认连接方式,但是最好还是指明连接类型。例:
SELECT e.fname,e.lname,d.name
-> FROM employee e INNER JOIN department d
-> ON e.dept_id=d.dept_id;
如果连接两个表的列名一样,可以将ON子句换成USING子句。不过,它只能在某些特殊情况下起到简化语法的作用,建议一直使用ON保持良好的编程习惯。
SELECT e.fname,e.lname,d.name
-> FROM employee e INNER JOIN department d
-> USING (dept_id);
外连接 OUTER JOIN
除去那些在两个表中都存在的值外,如果某个值只在一个表中出现,也将其加入新连接的表中。
3.多表连接(第五章,未完待续)
在多表连接中,没有前后顺序之分。如果想要按某种顺序连接,可在SELECT 后加上STRAIGHT_JOIN关键字使它后面跟的第一个表成为驱动表。
SELECT a.account_id,c.fed_id,e.fname,e.lname
-> FROM employee e INNER JOIN account a
-> ON e.emp_id = a.open_emp_id
-> INNER JOIN customer c
-> ON a.cust_id = c.cust_id
-> WHERE c.cust_type_cd = 'B';
将子查询的结果作为查询表
SELECT a.account_id ,a.cust_id,a.open_date,a.product_cd
-> FROM account a INNER JOIN
-> (SELECT emp_id,assigned_branch_id
-> FROM employee
-> WHERE start_date < '2007-01-01'
-> AND (title = 'Teller' OR title = 'Head Teller')) e
-> ON a.open_emp_id =e.emp_id
-> INNER JOIN
-> (SELECT branch_id
-> FROM branch
-> WHERE name = 'Woburn Branch') b
-> ON e.assigned_branch_id = b.branch_id;
连续两次使用同一个表
举个例子:表account与表employee要通过柜员编号id进行连接,一个柜员一条数据。而account表要与branch连接一次,来提取这个柜员的开户支行;employee也要与branch连接一次,来提取这个柜员工作所在的支行。为了服务器能将两次连接引用区分开来,也为了让我们不混淆,我们可以两次连接branch表并分别为其定义不同的别名,如下所示:
SELECT a.account_id ,e.emp_id,b_a.name open_branch,b_e.name emp_branch
-> FROM account a INNER JOIN branch b_a /*第一次起别名,与a连接*/
-> ON a.open_branch_id = b_a.branch_id
-> INNER JOIN employee e
-> ON a.open_emp_id = e.emp_id
-> INNER JOIN branch b_e
-> ON e.assigned_branch_id = b_e.branch_id
-> WHERE a.product_cd = 'CHK';
4.自连接
举例说明:employee表包含了一个指向自己的外键superior_emp_id(表示这个职员的主管领导),也就是说这一列(外键)是指向一个主键的,而这个主键就在自身这张表里,即为emp_id。这样如果我们想要同时列出职工和主管的姓名,只要为表定义不同的别名即可。如下示例。
这是表的情况,有助于理解题意:
自连接代码如下,很好理解:
SELECT CONCAT(e.fname," ",e.lname) employee,
-> CONCAT(s.fname," ",s.lname) superior
-> FROM employee e INNER JOIN employee s
-> ON s.superior_emp_id = e.emp_id;
查询结果如下:
注意:employee表中共有18行,但这个查询只返回了17行,因为Micheal Smith是银行总经理,他自己已经没有主管了,因此在这一行上的连接失败了。为了在结果集中包含Smith,则需要使用外连接,在后文中将对这一内容进行介绍。
(复习:①外键不要求数值各异:可以一个不同的条目对应于同一个主键,比如一个领导(外键表示的id为同一个数字,这个数字在主键列存在且仅存在一次)对应于好几个职员(好几个外键连接同一个主键,即外键列这个数字出现好几次);②定义外键约束时使用CONSTRAINT ... FOREIGN KEY (...) 语句即可);③使用CONCAT函数拼接字符串。)
5.相等连接与不等连接
很明显,不等连接时常常会产生笛卡尔积。如下例:
SELECT e.emp_id,e.start_date FROM employee e INNER JOIN product p
-> ON e.start_date >= p.date_offered;
结果是18*8的表(employee 18行,product 8行,没有过滤条件,全部符合连接条件,于是直接产生144行的新表。)
也可以产生不等的自连接:比如我们想让柜员们两两下一盘棋,把对弈名单列出来:
SELECT e1.emp_id A,concat(e1.fname," ",e1.lname," VS ",e2.fname," ",e2.lname) VERSUS ,e2.emp_id B
FROM employee e1 INNER JOIN employee e2
ON e1.emp_id < e2.emp_id;
17+16+...+1=153,没错嘿嘿,SQL真棒(我真棒)!
6.连接条件与过滤条件
在ON语句中使用表连接的连接条件;在WHERE语句中使用选择观测的过滤条件。尽量保持规范,有利于理解和维护,避免不必要的麻烦。
三、WHERE子句
- BETWEEN操作符:本质上是两个不严格不等式条件的组合。也就是说,BETEEN a AND b中的a和b是满足过滤条件的。
- IN 操作符:指明范围,和SAS中用法相同。可以使用NOT IN来求其补集。
SELECT accout_id,product_id,cust_id,avail_balance FROM account WHERE product_cd IN ('CHK','SAV','CD','MM');
- 可以使用子查询。
- 通配符:_ 表示一个字符 ; %表示任意数目的字符(可以是0)。与LIKE操作符搭配使用。下例表明指定字符串的第二个字必须是a,在它后面需要有一个字母e出现。
SELECT lname FROM employee WHERE lname LIKE '_a%e%';
- 可以使用正则表达式,它常用于脚本语言,此处不作详述。
- null.
null表示缺失值,就如同SAS中数值缺失的 . 与字符缺失的“ ”.注意,表达式可以为null,但不能等于null. 并且,两个null值不能判断为相等。
判断是否为null, 使用的语句为 ...WHERE a IS NULL ... 而非 ...WHERE a = NULL ...
!注意!如果错写为了等号,程序并不会报错。因此构建测试空值的查询时必须特别小心!
如果要查询不缺失的值,只要使用IS NOT NULL即可,与SAS相同。
四、GROUP BY 和HAVING子句
GROUP BY 根据列值对数据进行分组,也可以用于计数。
SELECT d.name,count(e.emp_id) as num_employees
-> FROM department d INNER JOIN employee e
-> ON d.dept_id = e.dept_id
-> GROUP BY d.name
-> HAVING num_employees > 2;
五、ORDER BY子句
排序 关键字ASC升序 DESC降序 默认升序。
如果根据SELECT子句中的列来排序,可以选择使用该列位于SELECT子句中的位置号来替代列名。比如:
SELECT emp_id,title,start_date,fname,lname
-> FROM employee
-> ORDER BY 2,5;
今日命令小结
还没写,嘿嘿,复习的时候再加上
这一篇就包含了SQL学习指南这本书第三到5章的内容啦~小测验还都没有做,这周末把整本书看完之后统一做。还有一句话:嘉伦可以更好看一点吗?小南辰王把我的心都偷走了,哎~