SQL学习指南第二篇
基本的查询语句
select 语句是由几个组件或者说子句构成。在 MySQL 中,select 子句必不可少,通常的查询语句会至少包含6个子句中的2~3个。下面的表列出了用于不同目的的各个子句。注意:SQL 语句不区分大小写,因此 SELECT 与 select 是相同的。
子句名称 | 使用目的 |
---|---|
select | 确定结果集中应该包含哪些列 |
from | 指明所要提取数据的表,以及这些表是如何连接的 |
where | 过滤不需要的数据 |
group by | 用于对具有相同列值的行进行分组 |
having | 过滤掉不需要的组 |
order by | 按一个或多个列,对最后结果集中的行进行排序 |
select 子句
select 子句不仅能返回 from 子句后面各表中所包含的列,还能返回字符串,数字,表达式,内建函数等。
例如:
SELECT emp_id, 'ACTIVE', emp_id * 3.14159, UPPER(lname) FROM employee;
如果只是执行一个内建函数或对简单的表达式求值,则可以完全省略 from 子句。
例如:
SELECT VERSION(), USER(), DATABASE();
列的别名
SELECT emp_id, 'ACTIVE' AS status, emp_id * 3.14159 AS empid_x_pi, UPPER(lname) AS last_name_upper FROM employee;
也可以去掉 AS 关键字。
去除重复的行
在 select 关键字之后加上 distinct 关键字。
限制查询结果
offset 关键字,limit 关键字可以指定跳过多少行数据以及检索的行数。
例如:
SELECT name FROM product LIMIT 5 OFFSET 3;
MySQL 和 MariaDB 支持简化版的 LIMIT 5 OFFSET 3 语句,即 LIMIT 3,5。逗号之前的值对应 OFFSET,逗号之后的值对应 LIMIT。
from 子句
表的概念
在 SQL 语言中,存在着3种类型的表:
- 永久表(使用 create table 语句创建的表)
- 临时表(子查询所返回的表以及使用 create temporary table temp_table_name 语句创建的表)
- 虚拟表(使用 create view 子句所创建的视图)
子查询
子查询指的是包含在另一个查询中的查询。子查询可以出现在 select 语句中的各个部分并且被包含在圆括号中,并对子查询得到的临时表定义表别名。
例如:
SELECT e.emp_id, e.fname, e.lname FROM (SELECT emp_id, fname, lname, start_date, title FROM employee) e;
在外围查询中,通过别名来引用子查询。
视图
由于视图虽表现得像一个表,但并不拥有任何数据,因此又称之为虚拟表。
例如:
CREATE VIEW person_vw AS SELECT person_id, fname, lname, YEAR(birth_date) year FROM person;
之后对其发出查询请求:
SELECT person_id, year FROM person_vw;
表连接
如果 from 子句出现了多个表,那么要求同时包含各表之间的连接条件。例如:
SELECT employee.emp_id, employee.fname, employee.lname, department.name AS dept_name
FROM employee INNER JOIN department
ON employee.dept_id = department.dept_id;
--这个是内连接
定义表别名
定义表别名与定义列别名是一样的,AS 关键字可省可不省。
where 子句
where 子句的作用是过滤掉我们不感兴趣的行。where 子句可以同时包含多个条件,它们之间使用操作符and, or或者not分割。
构建条件
1)相等条件 =
2)不等条件 != / <>( !=和<>通常可以互换。但是,并非所有 DBMS 都支持这两种不等于操作符。例如,Microsoft Access 支持<>而不支持!=。)
3)范围条件 >,<, >=, <=, between X and Y
4)成员条件 in ,not in
5) 匹配条件 like '含有通配符的搜索表达式' (表示1个字符,%表示任意数目的字符,DB2 不支持通配符)这样我们就可以匹配包含某个字符/字符串或具备固定格式的字符串了,注意不要过度使用通配符
6)检查是否为null——is null,相反的is not null。(通过过滤选择不包含指定值的所有行时,你可能希望返回含 NULL 值的行。但是这做不到。因为未知(unknown)有特殊的含义,数据库不知道它们是否匹配,所以在进行匹配过滤或非匹配过滤时,不会返回这些结果。)
例如:
SELECT * FROM employee WHERE end_date IS NULL AND NOT (title = 'Teller' OR start_date < '2002-01-01');
SELECT cust_id, fed_id FROM customer WHERE fed_id LIKE '___-__-____';
SELECT emp_id, fname, lname FROM employee WHERE lname LIKE 'F%' OR lname LIKE 'G%';
group by子句和having子句
group by 子句用于根据列值对数据分组,having 子句能够以与 where 子句类似的方式对分组数据进行过滤。
例如:
--查询包含两个雇员的部门名称,雇员总数
SELECT d.name, count(e.emp_id) num_employees FROM department d INNER JOIN employee e
ON d.dept_id = e.dept_id GROUP BY d.name HAVING count(e.emp_id) > 2;
order by子句
注意:ORDER BY 子句的位置,应该保证它是 SELECT 语句中最后一条子句。如果它不是最后的子句,将会出现错误消息。
指定排序方向
在排序时,可以通过关键字 asc 和 desc 指定是升序还是降序,默认是升序。
SELECT account_id, product_cd, open_date, avail_balance FROM account
ORDER BY avail_balance DESC;
--DESC关键字只应用到直接位于其前面的列名。
根据表达式排序
使用列数据对结果集进行排序十分有用,但有时或许还需要根据一些并非存放在数据库中的,甚至可能没有在查询中出现的内容进行排序。比如有个客户表,也许你会需要根据客户的个人识别号码的最后3位数字进行排序:
SELECT cust_id, cust_type_cd, city, state, fed_id FROM customer ORDER BY RIGHT(fed_id, 3);
根据数字占位符排序
除了根据列名来对结果进行排序外,我们还可以选择使用该列位于select子句中的位置号来替代列名。
例如:
SELECT emp_id, title, start_date, fname, lname FROM employee ORDER BY 2, 5;
多表查询
当我们需要将多张表的数据整合到一起时,需要使用连接机制进行多表查询。共有五种连接类型:内连接,外连接,交叉连接,自然连接,自连接。SQL是一种非过程化语言,因此多表连接时 from 子句中各表出现的顺序并不重要。
内连接
内连接返回的结果集是两个表中所有相匹配的数据,通过 on 子句来作为搜索条件。默认情况下,DBMS将多表查询按内连接即 inner join 来执行,不过最好在from子句中显示指定连接类型。还可以将子查询结果作为查询表来进行内连接。
例如:
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;
--注意:主查询中缺少了where子句,因为所有的过滤条件都包含于子查询中,所以主查询不需要任何过滤条件。
视图
为什么使用视图
视图是一种简单的数据查询机制。不同于表,视图不涉及数据存储,因此不同担心视图会充满磁盘空间。通过命名 select 语句来创建视图,然后将这个查询保存起来供其他用户使用,而其他用户使用这个视图时就像他们自己在直接查询数据。使用视图具有以下优点:
- 数据安全
- 数据聚合
- 隐藏复杂性
- 连接分区数据