3.4 查询语句
3.4.1 单表查询语句
查询student表中所有数据的语句为:
select no, student_name, age from student;
其中“SELECT”是关键字,表示要查询,后面跟多个列名,各列之间使用逗号分隔。其后的“FROM”是关键字,后面跟表的名称。各个列可以是表的列名,也可以是一个表达式,如下:
select age+5 from student;
表达式中可以包括表的列,也可以只是一个与表列无关的表达式,如下:
select no, 3+5 from student;
当表达式与表的列无关时,在PostgreSQL和MySQL中可以不使用“FROM 表名”,这样一来,就可以当作计算器使用了:
osdba=# select 55+88;
?column?
----------
143
(1 row)
osdba=# select 10*2,3*5+2;
?column? | ?column?
----------+----------
20 | 17
(1 row)
如果想查询表中所有列的数据,则可以使用“*”代表所有列,如下:
select * from student;
3.4.2 过滤条件的查询
SELECT语句后面可以通过指定WHERE子句来指定要查询哪条记录或哪些记录。比如,要查询学号为3的记录,其SQL语句为:
osdba=# SELECT * FROM student where no=3;
no | student_name | age
----+--------------+-----
3 | 王明充 | 13
(1 row)
在WHERE条件中也可以使用大于、小于的表达式。比如,想查询年龄大于等于15岁的学生,其语句如下:
osdba=# SELECT * FROM student where age >= 15;
no | student_name | age
----+--------------+-----
1 | 张三 | 15
2 | 李四 | 15
(2 rows)
3.4.3 排序
使用排序子句可以对查询出的数据进行排序,排序子句是在SELECT语句后面再加上“ORDER BY”子句。比如,希望查询出来的结果按年龄排序,则查询语句如下:
osdba=# SELECT * FROM student ORDER BY age;
no | student_name | age
----+--------------+-----
3 | 王明充 | 13
1 | 张三 | 15
2 | 李四 | 15
(3 rows)
排序子句“ORDER BY”应该在“WHERE”子句之前,如果顺序错了,会报错:
osdba=# SELECT * FROM student ORDER BY age WHERE age >= 15;
ERROR: syntax error at or near "WHERE"
LINE 1: SELECT * FROM student ORDER BY age WHERE age >= 15;
把“ORDER BY”子句放到“WHERE”子句后面就不报错了:
osdba=# SELECT * FROM student WHERE age >= 15 ORDER BY age;
no | student_name | age
----+--------------+-----
1 | 张三 | 15
2 | 李四 | 15
(2 rows)
还可以按多个列进行排序。比如,根据“age”和“student_name”两个列来排序:
osdba=# SELECT * FROM student ORDER BY age,student_name;
no | student_name | age
----+--------------+-----
3 | 王明充 | 13
2 | 李四 | 15
1 | 张三 | 15
(3 rows)
也可以在排序子句的列名后加“DESC”进行倒序排序:
osdba=# SELECT * FROM student ORDER BY age DESC;
no | student_name | age
----+--------------+-----
1 | 张三 | 15
2 | 李四 | 15
3 | 王明充 | 13
(3 rows)
osdba=# SELECT * FROM student ORDER BY age DESC,student_name;
no | student_name | age
----+--------------+-----
2 | 李四 | 15
1 | 张三 | 15
3 | 王明充 | 13
(3 rows)
3.4.4 分组查询
如果需要统计不同年龄的学生人数,可以使用分组查询,分组查询子句的关键字为“GROUP BY”,用法如下:
osdba=# SELECT age, count(*) FROM student GROUP BY age;
age | count
-----+-------
15 | 2
13 | 1
(2 rows)
从上面可以看出,使用“GROUP BY”语句时,需要使用聚合函数,常用的聚合函数为“count”、“sum”等。
3.4.5 表join
表join也称为多表关联查询。假设有一张班级表class,建表语句为:
CREATE TABLE class(no int primary key, class_name varchar(40));
表中的“no”表示班级编号,“class_name”表示班级名称。
插入一些测试数据:
osdba=# INSERT INTO class VALUES(1,'初二(1)班');
INSERT 0 1
osdba=# INSERT INTO class VALUES(2,'初二(2)班');
INSERT 0 1
osdba=# INSERT INTO class VALUES(3,'初二(3)班');
INSERT 0 1
osdba=# INSERT INTO class VALUES(4,'初二(4)班');
INSERT 0 1
osdba=# SELECT * FROM class;
no | class_name
----+------------
1 | 初二(1)班
2 | 初二(2)班
3 | 初二(3)班
4 | 初二(4)班
(4 rows)
还有另一张学生表student,建表语句为:
CREATE TABLE student(no int primary key, student_name varchar(40), age int, class_no int);
也插入一些数据:
osdba=# INSERT INTO student VALUES(1, '张三', 14, 1);
INSERT 0 1
osdba=# INSERT INTO student VALUES(2, '吴二', 15, 1);
INSERT 0 1
osdba=# INSERT INTO student VALUES(3, '李四', 13, 2);
INSERT 0 1
osdba=# INSERT INTO student VALUES(4, '吴三', 15, 2);
INSERT 0 1
osdba=# INSERT INTO student VALUES(5, '王二', 15, 3);
INSERT 0 1
osdba=# INSERT INTO student VALUES(6, '李三', 14, 3);
INSERT 0 1
osdba=# INSERT INTO student VALUES(7, '吴二', 15, 4);
INSERT 0 1
osdba=# INSERT INTO student VALUES(8, '张四', 14, 4);
INSERT 0 1
osdba=# SELECT * FROM student;
no | student_name | age | class_no
----+--------------+-----+----------
1 | 张三 | 14 | 1
2 | 吴二 | 15 | 1
3 | 李四 | 13 | 2
4 | 吴三 | 15 | 2
5 | 王二 | 15 | 3
6 | 李三 | 14 | 3
7 | 吴二 | 15 | 4
8 | 张四 | 14 | 4
若现在想查询出每个学生与班级的关系,那么此时就需要关联查询两张表:
SELECT student_name, class_name FROM student, class
WHERE student.class_no = class.no;
查询出来的结果如下:
osdba=# SELECT student_name, class_name FROM student, class
WHERE student.class_no = class.no;
student_name | class_name
--------------+------------
张三 | 初二(1)班
吴二 | 初二(1)班
李四 | 初二(2)班
吴三 | 初二(2)班
王二 | 初二(3)班
李三 | 初二(3)班
吴二 | 初二(4)班
张四 | 初二(4)班
(8 rows)
表关联查询就是在WHERE条件上加上需要关联的条件(两张表关联):
WHERE student.class_no = class.no;
由于在两张表中,有一些列的名称是重复的,如在表student中no表示学生号,而在表class中表示班级号,所以在关键条件中要明确使用“表名”加“列名”来唯一定位这个列。如果输入的表名比较长,不是很方便,这时可以给表起个别名,如下所示:
SELECT student_name, class_name FROM student a, class b
WHERE a.class_no = b.no;
上面的语句中,给表“student”起的别名为“a”,表“class”的别名为“b”,这时条件表达式中“b.no”就代表了表“class”中的“no”列。
在关联查询的WHERE子句中可以再加上其他的过滤条件,如下:
osdba=# SELECT student_name, class_name FROM student a, class b
WHERE a.class_no = b.no AND a.age > 14;
student_name | class_name
---------------+------------
吴二 | 初二(1)班
吴三 | 初二(2)班
王二 | 初二(3)班
吴二 | 初二(4)班
(4 rows)