Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » SQL Anywhere 服务器 - SQL 的用法 » 查询和修改数据 » 连接:从多个表检索数据 » 专用连接

 

连接中的重复相关名(星形连接)

使用重复表名称的原因是为了创建星形连接。在星形连接中,一个表或视图与若干其它表或视图相连接。

若要创建星形连接,应在 FROM 子句中多次使用同一个表名称、视图名称或相关名。这是对 ANSI/ISO SQL 标准的扩展。能够使用重复名并不添加任何附加功能,但这可以使某些查询写起来更加容易。

为使语法有意义,重复名必须位于不同的连接中。如果在同一连接中使用两次表名称或视图名称,则忽略第二个实例。例如,FROM A,AFROM A CROSS JOIN A 均解释为 FROM A

在 SQL Anywhere 中,以下示例是有效的,其中 A、B 和 C 是表。在此示例中,表 A 的同一实例同时连接到 B 和 C。请注意,在星形连接中需要使用逗号分隔这些连接。在星形连接中使用逗号是星形连接语法所特有的。

SELECT *
FROM A LEFT OUTER JOIN B ON A.x = B.x,
     A LEFT OUTER JOIN C ON A.y = C.y;

下一个示例是等效的。

SELECT *
FROM A LEFT OUTER JOIN B ON A.x = B.x,
     C RIGHT OUTER JOIN A ON A.y = C.y;

这两个示例都等效于以下标准 ANSI/ISO 语法。(括号是可选的。)

SELECT *
FROM (A LEFT OUTER JOIN B ON A.x = B.x)
LEFT OUTER JOIN C ON A.y = C.y;

在下一个示例中,将表 A 连接到三个表:B、C 和 D。

SELECT *
FROM A JOIN B ON A.x = B.x,
     A JOIN C ON A.y = C.y,
     A JOIN D ON A.w = D.w;

这等效于以下标准 ANSI/ISO 语法。(括号是可选的。)

SELECT *
FROM ((A JOIN B ON A.x = B.x)
JOIN C ON A.y = C.y)
JOIN D ON A.w = D.w;

遇到复杂连接时,画图会很有帮助。上面的示例可通过下图描述,该图示阐释表 B、C 和 D 通过表 A 连接。

表 A 在中央,表 B、C 和 D 分别与其连接。
注意

只有 extended_join_syntax 选项为 On(缺省值)时,才能使用重复表名称。

有关详细信息,请参见extended_join_syntax 选项 [数据库]

示例 1

创建给 Rollin Overbey 下订单的客户名称的列表。请注意,FROM 子句中的表 Employees 的任何列均未出现在结果中。所连接的任何列—例如 Customers.ID 或 Employees.EmployeeID—也未出现在结果中。不过,只有在 FROM 子句中使用 Employees 表才能实现该连接。

SELECT Customers.GivenName, Customers.Surname,
   SalesOrders.OrderDate
FROM   SalesOrders KEY JOIN Customers,
      SalesOrders KEY JOIN Employees
WHERE Employees.GivenName = 'Rollin'
  AND Employees.Surname = 'Overbey'
ORDER BY SalesOrders.OrderDate;
GivenName Surname OrderDate
Tommie Wooten 2000-01-03
Michael Agliori 2000-01-08
Salton Pepper 2000-01-17
Tommie Wooten 2000-01-23
... ... ...

以下是采用标准 ANSI/ISO 语法的等效语句:

SELECT Customers.GivenName, Customers.Surname,
  SalesOrders.OrderDate
FROM SalesOrders JOIN Customers
  ON SalesOrders.CustomerID = 
   Customers.ID
JOIN Employees
  ON SalesOrders.SalesRepresentative = 
   Employees.EmployeeID
WHERE Employees.GivenName = 'Rollin'
  AND Employees.Surname = 'Overbey'
ORDER BY SalesOrders.OrderDate;
示例 2

本示例回答的问题是:每位客户订购每种产品的数量是多少?谁是获得订单的销售人员的经理?

为回答这些问题,应首先列出您需要检索的信息。在此例子中,需要检索的信息是产品、数量、客户名称和经理姓名。接下来,列出保存这些信息的表。它们是 Products、SalesOrderItems、Customers 和 Employees。查看 SQL Anywhere 示例数据库的结构时(请参见示例数据库模式),您将注意到,这些表全部通过 SalesOrders 表进行关联。您可以为 SalesOrders 表创建星形连接,以检索其它表中的信息。

此外,您还需要创建自连接,以便获取经理姓名,因为 Employees 表包含经理的 ID 号和所有雇员的姓名,但没有仅列出经理姓名的列。有关详细信息,请参见自连接

以下语句围绕 SalesOrders 表创建星形连接。这些连接全都是外连接,因此结果集将包括所有客户。有些客户没有下订单,因此对应这些客户的其它值为空。结果集中的列是客户、产品、订购的数量以及销售人员的经理的姓名。

SELECT Customers.GivenName, Products.Name,
  SUM(SalesOrderItems.Quantity), m.GivenName
FROM SalesOrders
    KEY RIGHT OUTER JOIN Customers,
   SalesOrders
    KEY LEFT OUTER JOIN SalesOrderItems
    KEY LEFT OUTER JOIN Products,
      SalesOrders
    KEY LEFT OUTER JOIN Employees AS e
    LEFT OUTER JOIN Employees AS m
        ON (e.ManagerID = m.EmployeeID)
WHERE Customers.State = 'CA'
GROUP BY Customers.GivenName, Products.Name, m.GivenName
ORDER BY SUM(SalesOrderItems.Quantity) DESC, 
   Customers.GivenName;
GivenName Name SUM(SalesOrderItems.Quantity) GivenName
Sheng Baseball Cap 240 Moira
Laura Tee Shirt 192 Moira
Moe Tee Shirt 192 Moira
Leilani Sweatshirt 132 Moira
... ... ... ...

以下是此星形连接中各表的图示。箭头指示这些外连接的方向(左或右)。正如您所看到的,整个客户列表是贯穿所有连接来维护的。

Customers 表在右侧,用一个箭头指向 SalesOrders 表。从 SalesOrders 表有两个箭头均指向左侧。其中一个箭头指向 SalesOrderItems,再从 SalesOrderItems 到 Products。另一个箭头指向 Employees AS e,再从 Employees AS e 到 Employees AS m。

以下标准 ANSI/ISO 语法等效于示例 2 中的星形连接。

SELECT Customers.GivenName, Products.Name,
  SUM(SalesOrderItems.Quantity), m.GivenName
FROM SalesOrders LEFT OUTER JOIN SalesOrderItems
    ON SalesOrders.ID = SalesOrderItems.ID
  LEFT OUTER JOIN Products
    ON SalesOrderItems.ProductID = Products.ID
  LEFT OUTER JOIN Employees as e
    ON SalesOrders.SalesRepresentative = e.EmployeeID
  LEFT OUTER JOIN Employees as m
    ON e.ManagerID = m.EmployeeID
  RIGHT OUTER JOIN Customers
    ON SalesOrders.CustomerID = Customers.ID
WHERE Customers.State = 'CA'
GROUP BY Customers.GivenName, Products.Name, m.GivenName
ORDER BY SUM(SalesOrderItems.Quantity) DESC, 
   Customers.GivenName;