SQL 入门教程:作为计算字段使用子查询

本文内容

目录汇总:SQL 零基础入门教程

使用子查询的另一方法是创建计算字段。假如需要显示 Customers 表中每个顾客的订单总数。订单与相应的顾客 ID 存储在 Orders 表中。

执行这个操作,要遵循下面的步骤:

(1) 从 Customers 表中检索顾客列表;

(2) 对于检索出的每个顾客,统计其在 Orders 表中的订单数目。

正如前两课所述,可以使用 SELECT COUNT(*) 对表中的行进行计数,并且通过提供一条 WHERE 子句来过滤某个特定的顾客 ID,仅对该顾客的订单进行计数。例如,下面的代码对顾客 1000000001 的订单进行计数:

输入▼

1
2
3
SELECT COUNT(*) AS orders
FROM Orders
WHERE cust_id = 1000000001;

要对每个顾客执行 COUNT(*),应该将它作为一个子查询。请看下面的代码:

输入▼

1
2
3
4
5
6
7
SELECT cust_name,
       cust_state,
       (SELECT COUNT(*)
        FROM Orders
        WHERE Orders.cust_id = Customers.cust_id) AS orders
FROM Customers
ORDER BY cust_name;

输出▼

cust_name                     cust_state     orders
-------------------------     ----------     ------
Fun4All                       IN             1
Fun4All                       AZ             1
Kids Place                    OH             0
The Toy Store                 IL             1
Village Toys                  MI             2

分析▼

这条 SELECT 语句对 Customers 表中每个顾客返回三列:cust_namecust_stateordersorders 是一个计算字段,它是由圆括号中的子查询建立的。该子查询对检索出的每个顾客执行一次。在此例中,该子查询执行了 5 次,因为检索出了 5 个顾客。

子查询中的 WHERE 子句与前面使用的 WHERE 子句稍有不同,因为它使用了完全限定列名,而不只是列名(cust_id)。它指定表名和列名(Orders.cust_idCustomers.cust_id)。下面的 WHERE 子句告诉 SQL,比较 Orders 表中的 cust_id 和当前正从 Customers 表中检索的 cust_id

1
WHERE Orders.cust_id = Customers.cust_id

用一个句点分隔表名和列名,在有可能混淆列名时必须使用这种语法。在这个例子中,有两个 cust_id 列:一个在 Customers 中,另一个在 Orders 中。如果不采用完全限定列名,DBMS 会认为要对 Orders 表中的 cust_id 自身进行比较。因为

1
SELECT COUNT(*) FROM Orders WHERE cust_id = cust_id

总是返回 Orders 表中订单的总数,而这个结果不是我们想要的:

输入▼

1
2
3
4
5
6
7
SELECT cust_name,
       cust_state,
       (SELECT COUNT(*)
        FROM Orders
        WHERE cust_id = cust_id) AS orders
FROM Customers
ORDER BY cust_name;

输出▼

cust_name                     cust_state     orders
-------------------------     ----------     ------
Fun4All                       IN             5
Fun4All                       AZ             5
Kids Place                    OH             5
The Toy Store                 IL             5
Village Toys                  MI             5

虽然子查询在构造这种 SELECT 语句时极有用,但必须注意限制有歧义的列。

注意:完全限定列名

你已经看到了为什么要使用完全限定列名,没有具体指定就会返回错误结果,因为 DBMS 会误解你的意思。有时候,由于出现冲突列名而导致的歧义性,会引起 DBMS 抛出错误信息。例如,WHEREORDER BY 子句 指定的某个列名可能会出现在多个表中。好的做法是,如果在 SELECT 语句 中操作多个表,就应使用完全限定列名来避免歧义。

提示:不止一种解决方案

正如这一部分前面所述,虽然这里给出的样例代码运行良好,但它并不是解决这种数据检索的最有效方法。在后面两个部分学习 JOIN 时,我们还会遇到这个例子。

请参阅

(完)

comments powered by Disqus

本文内容