
少校 1转71级 守护100级 UID20
回帖1890
主题0
积分9648
阅读权限170
注册时间2006-5-21
最后登录2009-3-11
在线时间1399 小时
|
楼主 |
发表于 2007-10-16 23:05
|
显示全部楼层
1.4.1.5. Having
HAVING 子句运做起来非常象 WHERE 子句, 只用于对那些满足 HAVING 子句里面给出的条件的组进行计算。 其实,WHERE 在分组和聚集之前过滤掉我们不需要的输入行, 而 HAVING 在 GROUP 之后那些不需要的组. 因此,WHERE 无法使用一个聚集函数的结果. 而另一方面,我们也没有理由写一个不涉及聚集函数的 HAVING. 如果你的条件不包含聚集,那么你也可以把它写在 WHERE 里面, 这样就可以避免对那些你准备抛弃的行进行的聚集运算.
Example 1-7. Having
如果我们想知道那些销售超过一个部件的供应商,使用下面查询:
SELECT S.SNO, S.SNAME, COUNT(SE.PNO)
FROM SUPPLIER S, SELLS SE
WHERE S.SNO = SE.SNO
GROUP BY S.SNO, S.SNAME
HAVING COUNT(SE.PNO) > 1;
and get:
SNO | SNAME | COUNT
-----+-------+-------
1 | Smith | 2
3 | Adams | 2
4 | Blake | 3
1.4.1.6. 子查询
在 WHERE 和 HAVING 子句里,允许在任何要产生数值的地方使用子查询 (子选择)。 这种情况下,该值必须首先来自对子查询的计算。子查询的使用扩展了 SQL 的表达能力。
Example 1-8. 子查询
如果我们想知道所有比名为 'Screw' 的部件贵的部件,我们可以用下面的查询:
SELECT *
FROM PART
WHERE PRICE > (SELECT PRICE FROM PART
WHERE PNAME='Screw');
结果是:
PNO | PNAME | PRICE
-----+---------+--------
3 | Bolt | 15
4 | Cam | 25
当我们检查上面的查询时会发现出现了两次 SELECT 关键字。 第一个在查询的开头 - 我们将称之为外层 SELECT - 而另一个在 WHERE 子句里面,成为一个嵌入的查询 - 我们将称之为内层 SELECT。 对外层 SELECT 的每条记录都必须先计算内层 SELECT。在完成所有计算之后, 我们得知名为 'Screw' 部件的记录的价格, 然后我们就可以检查那些价格更贵的记录了。 (实际上,在本例中,内层查询只需要执行一次, 因为它不依赖于外层查询高等状态.)
如果我们想知道那些不销售任何部件的供应商 (比如说,我们想把这些供应商从数据库中删除),我们用:
SELECT *
FROM SUPPLIER S
WHERE NOT EXISTS
(SELECT * FROM SELLS SE
WHERE SE.SNO = S.SNO);
在我们的例子里,结果列将是空的,因为每个供应商至少销售一个部件。 请注意我们在 WHERE 子句的内层 SELECT 里使用了来自外层 SELECT 的 S.SNO。 正如前面所说的,子查询为每个外层查询计算一次,也就是说, S.SNO 的值总是从外层 SELECT 的实际记录中取得的。
1.4.1.7. 在 FROM 里面的子查询
一种有些特别的子查询的用法是把它们放在 FROM 子句里. 这个特性很有用,因为这样的子查询可以输出多列和多行, 而在表达式里使用的子查询必须生成一个结果. FROM 里的子查询还可以让我们获得多于一个回合的分组/聚集特性, 而不需要求助于临时表.
Example 1-9. FROM 里面的子查询
如果我们想知道在所有我们的供应商中的最高平均部件价格的那家, 我们不能用 MAX(AVG(PRICE)),但我们可以这么写:
SELECT MAX(subtable.avgprice)
FROM (SELECT AVG(P.PRICE) AS avgprice
FROM SUPPLIER S, PART P, SELLS SE
WHERE S.SNO = SE.SNO AND
P.PNO = SE.PNO
GROUP BY S.SNO) subtable;
这个子查询为每个供应商返回一行(因为它的 GROUP BY) 然后我们在外层查询对所有行进行聚集.
1.4.1.8. Union, Intersect, Except(联合,相交,相异)
这些操作符分别计算两个子查询产生的元组的联合,相交和集合理论里的相异。
Example 1-10. Union, Intersect, Except
下面的例子是 UNION 的例子:
SELECT S.SNO, S.SNAME, S.CITY
FROM SUPPLIER S
WHERE S.SNAME = 'Jones'
UNION
SELECT S.SNO, S.SNAME, S.CITY
FROM SUPPLIER S
WHERE S.SNAME = 'Adams';
产生结果:
SNO | SNAME | CITY
-----+-------+--------
2 | Jones | Paris
3 | Adams | Vienna
下面是相交( INTERSECT)的例子:
SELECT S.SNO, S.SNAME, S.CITY
FROM SUPPLIER S
WHERE S.SNO > 1
INTERSECT
SELECT S.SNO, S.SNAME, S.CITY
FROM SUPPLIER S
WHERE S.SNO < 3;
产生结果:
SNO | SNAME | CITY
-----+-------+--------
2 | Jones | Paris
两个查询都会返回的元组是那条 SNO=2 的
最后是一个 EXCEPT 的例子:
SELECT S.SNO, S.SNAME, S.CITY
FROM SUPPLIER S
WHERE S.SNO > 1
EXCEPT
SELECT S.SNO, S.SNAME, S.CITY
FROM SUPPLIER S
WHERE S.SNO > 3;
结果是:
SNO | SNAME | CITY
-----+-------+--------
2 | Jones | Paris
3 | Adams | Vienna
1.4.2. 数据定义
在 SQL 语言里包含一套用于数据定义的命令。
1.4.2.1. 创建表
数据定义的最基本的命令是创建一个新关系(新表)的命令。 CREATE TABLE 命令的语法如下:
CREATE TABLE table_name
(name_of_attr_1 type_of_attr_1
[, name_of_attr_2 type_of_attr_2
[, ...]]);
Example 1-11. 创建表
要创建 供应商和部件数据库里的表,要使用下面的 SQL 语句:
CREATE TABLE SUPPLIER
(SNO INTEGER,
SNAME VARCHAR(20),
CITY VARCHAR(20));
CREATE TABLE PART
(PNO INTEGER,
PNAME VARCHAR(20),
PRICE DECIMAL(4 , 2));
CREATE TABLE SELLS
(SNO INTEGER,
PNO INTEGER); |
|