一些Oracle SQL语句的例子
例子所是用的数据库表。(这些表不包括任何约束,仅用于SELECT连接查询)
CREATE TABLE xapp_classes(
id NUMBER(4),
name VARCHAR2(20)
);
CREATE TABLE xapp_students(
id NUMBER(4),
classid NUMBER(4),
name VARCHAR2(20)
age NUMBER(3),
);
CREATE TABLE xapp_courses(
id NUMBER(4),
name VARCHAR2(20)
);
CREATE TABLE xapp_students_courses(
studentid NUMBER(4),
courseid NUMBER(4),
points NUMBER(3)
);
CREATE TABLE xapp_grades(
name VARCHAR2(4),
minp NUMBER(3),
maxp NUMBER(3)
);
xapp_grades表所使用的数据
INSERT INTO xapp_grades VALUES('A', 90, 100);
INSERT INTO xapp_grades VALUES('B', 80, 89);
INSERT INTO xapp_grades VALUES('C', 70, 79);
INSERT INTO xapp_grades VALUES('D', 60, 69);
INSERT INTO xapp_grades VALUES('F', 0, 59);
等值连接
SELECT s.name "Student",
c.name "Course"
FROM xapp_students s,
xapp_courses c,
xapp_students_courses sc
WHERE s.id = sc.studentid
AND sc.courseid = c.id
不等值连接
SELECT s.name "Student",
c.name "Course",
g.name "Grade"
FROM xapp_students s,
xapp_courses c,
xapp_students_courses sc,
xapp_grades g
WHERE s.id = sc.studentid
AND sc.courseid = c.id
AND sc.points BETWEEN g.minp AND g.maxp
-- 通过xapp_grades表输出分数对应的等级
自连接
SELECT DISTINCT s1.name
FROM xapp_students s1,
xapp_students s2
WHERE s1.name = s2.name
AND s1.id <> s2.id
外连接
SELECT s.name "Student",
NVL(c.name, 'No Class') "Class"
FROM xapp_students s,
xapp_classes c
WHERE s.classid = c.id(+)
分组查询
语法:
SELECT fields FROM table
WHERE expression
GROUP BY field
HAVING expression
fields中只能有已分组字段与表达式和聚合函数
WHERE的判断条件不能有已分组的内容
HAVING的判断条件只能包括已分组的内容
Example 1
SELECT classid, COUNT(*)
FROM xapp_students
GROUP BY classid
Example 2
SELECT g.name "Grade",
COUNT(*) "Student Count"
FROM xapp_students_courses sc,
xapp_grades g
WHERE sc.points BETWEEN g.minp AND g.maxp
GROUP BY g.name
Example 3
SELECT (TRUNC(points/10)*10)||'-'||( TRUNC(points/10)*10+9) "Point",
COUNT(*) "Student Count"
FROM xapp_students_courses
GROUP BY TRUNC(points/10)
-- 按points分数段分组
-- 通过表达式分组,SELECT子句中只能出现分组的表达式
Example 4
SELECT NVL(c.name, 'No Class') "Class Name",
COUNT(*) "Student Count"
FROM xapp_students s,
xapp_classes c
WHERE s.classid = c.id(+)
GROUP BY c.name
Example 5
SELECT
NVL((SELECT c.name FROM xapp_classes c
WHERE c.id=s.classid),'No Class') "Class Name",
COUNT(*) "Student Count"
FROM xapp_students s
GROUP BY classid
ORDER BY COUNT(*)
-- 与前一个例子相比,这里通过NUMBER类型的字段classid分组,
-- 而没用通过CHAR类型字段分组
-- 在SELECT子句中使用自查询
-- 效率与前一个例子相比?
Example 6
SELECT age, COUNT(*)
FROM xapp_students
GROUP BY age
HAVING COUNT(*) > 2
ORDER BY age
-- HAVING子句的使用
子查询的2个例子
SELECT * FROM xapp_students
WHERE age > (SELECT AVG(age) FROM xapp_students)
SELECT name
FROM xapp_students
WHERE id IN (SELECT DISTINCT studentid
FROM xapp_students_courses
WHERE points IS NOT NULL)
ROWNUM
-- ROWNUM与ORDER BY同时存在时,先计算ROWNUM,再进行排序
-- (与SQL Server的TOP *不同)
-- 需要嵌套1层子查询实现该功能
-- 错误,不能选择出按name排序前4的记录
SELECT id, name
FROM xapp_students
ORDER BY name
WHERE ROWNUM <= 4
-- 正确
SELECT id, name
FROM (SELECT id, name
FROM xapp_students
ORDER BY name)
WHERE ROWNUM <=4
选择第2条到第4条记录
SELECT id, name
FROM (SELECT id, name, ROWNUM rn
FROM xapp_students
WHERE ROWNUM <= 4)
WHERE rn >= 2
选择排序后第2条到第4条记录
SELECT id, name
FROM (SELECT id, name, ROWNUM rn
FROM (SELECT id, name
FROM xapp_students
ORDER BY name)
)
WHERE rn BETWEEN 2 AND 4