在关系数据库系统(如 Access)中,经常需要同时从多个表中提取信息。 这可以通过使用 SQL JOIN 语句来完成,该语句使您能够从已定义关系的表中检索记录,无论这种关系是一对一、一对多还是多对多。
INNER JOIN
INNER JOIN (也称为等效联接)是最常用类型的联接。 此联接通过匹配表之间共有的字段值来从两个或多个表中检索行。 联接的字段必须具有相似的数据类型,不能联接"备注"或"OLE 对象"数据类型。
若要构建 INNER JOIN 语句,请在 SELECT 语句的 FROM 子句中使用 INNER JOIN 关键字。
本示例使用 INNER JOIN 构建一个包含所有具有发票的客户以及这些发票的日期和金额的结果集。
SELECT [Last Name], InvoiceDate, Amount
FROM tblCustomers INNER JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID
ORDER BY InvoiceDate
请注意,表名称除以 INNER JOIN 关键字,关系比较在 ON 关键字 (keyword) 之后。 对于关系比较,还可以使用 <、、、><=、>=或 <> 运算符,还可以使用 BETWEEN 关键字 (keyword) 。 还要注意,两个表中的 ID 字段只能在关系比较中使用;它们不是最终结果集的一部分。
若要进一步限定 SELECT 语句,可以在 ON 子句中的联接比较后使用 WHERE 子句。
以下示例将结果集缩小为仅包括日期为 1998 年 1 月 1 日之后的发票。
SELECT [Last Name], InvoiceDate, Amount
FROM tblCustomers INNER JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID
WHERE tblInvoices.InvoiceDate > #01/01/1998#
ORDER BY InvoiceDate
当必须联接多个表时,可以嵌套 INNER JOIN 子句。 以下示例以上一个 SELECT 语句为基础建立结果集,而且还通过为 tblShipping 表添加 INNER JOIN 来包括每个客户所在的城市和省/市/自治区。
SELECT [Last Name], InvoiceDate, Amount, City, State
FROM (tblCustomers INNER JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID)
INNER JOIN tblShipping
ON tblCustomers.CustomerID=tblShipping.CustomerID
ORDER BY InvoiceDate
请注意,第一个 JOIN 子句括在括号中,以使其在逻辑上与第二个 JOIN 子句分开。 还可以通过在 FROM 子句中使用第二个表名的别名将表联接到自身。 假设要查找所有具有重复姓氏的客户记录。 可以通过为第二个表创建别名“A”并且检查不同的名字完成此操作。
SELECT tblCustomers.[Last Name],
tblCustomers.[First Name]
FROM tblCustomers INNER JOIN tblCustomers AS A
ON tblCustomers.[Last Name]=A.[Last Name]
WHERE tblCustomers.[First Name]<>A.[First Name]
ORDER BY tblCustomers.[Last Name]
OUTER JOIN
An OUTER JOIN is used to retrieve records from multiple tables while preserving records from one of the tables, even if there is no matching record in the other table. There are two types of OUTER JOINs that the Access database engine supports: LEFT OUTER JOINs and RIGHT OUTER JOINs.
想象两个表彼此挨着:一个表在左边,一个表在右边。 LEFT OUTER JOIN 选择右表中与关系比较条件匹配的所有行,并且还会从左侧表中选择所有行,即使右侧表中不存在匹配项也是如此。 RIGHT OUTER JOIN 恰好与 LEFT OUTER JOIN 相反;右表中的所有行都被保留。
例如,假设要确定已开给每个客户的发票总额,但如果某个客户没有发票,希望通过显示单词"NONE"来说明这种情况。
SELECT [Last Name] & ', ' & [First Name] AS Name,
IIF(Sum(Amount) IS NULL,'NONE',Sum(Amount)) AS Total
FROM tblCustomers LEFT OUTER JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID
GROUP BY [Last Name] & ', ' & [First Name]
上一个 SQL 语句中实现了三项操作。 第一是使用字符串连接运算符“&”。 此运算符允许您将两个或多个字段作为一个字符串联接在一起。 第二是使用直接 if (IIf) 语句,该语句用于检查合计是否为空。 如果是,则语句返回单词“NONE”。如果总计不为 null,则返回值。 最后是使用 OUTER JOIN 子句。 使用 LEFT OUTER JOIN 可保留左表中的行,以便看到所有客户,甚至那些没有发票的客户。
OUTER JOIN 在多表联接中可以嵌套在 INNER JOIN 内,但 INNER JOIN 不能嵌套在 OUTER JOIN 内。
笛卡儿积
讨论联接时经常遇到的一个术语就是笛卡儿积。 笛卡尔乘积定义为“所有表中所有行的所有可能组合”。例如,如果要在没有任何类型的限定或联接类型的情况下联接两个表,则会获得笛卡尔乘积。
SELECT *
FROM tblCustomers, tblInvoices
这并非一件好事,尤其是对于那些包含成百上千行的表。 应始终限定联接来避免创建笛卡儿积。
UNION 运算符
尽管 UNION 运算符(也称为联合查询)在技术上不是一个联接,但这里将它包括在内,是因为它涉及将多个数据源中的数据合并为一个结果集,这类似于某些类型的联接。 UNION 运算符用于将表、 SELECT 语句或查询中的数据联接在一起,而不考虑任何重复的行。 两个数据源必须具有相同数量的字段,但字段不必是相同的数据类型。 假设你有一个与 Customers 表具有相同结构的员工表,并且你希望通过组合这两个表来生成名称和电子邮件地址列表。
SELECT [Last Name], [First Name], Email
FROM tblCustomers
UNION
SELECT [Last Name], [First Name], Email
FROM tblEmployees
若要从这两个表中检索所有字段,可以使用 TABLE 关键字 (keyword) ,如下所示。
TABLE tblCustomers
UNION
TABLE tblEmployees
UNION 运算符不会在这两个表中显示任何完全重复的记录,但可以使用 UNION 关键字 (keyword) 后的 ALL 谓词来重写这一点,如下所示:
SELECT [Last Name], [First Name], Email
FROM tblCustomers
UNION ALL
SELECT [Last Name], [First Name], Email
FROM tblEmployees
TRANSFORM 语句
尽管 TRANSFORM 语句(也称为交叉表查询)在技术上也不认为是一个联接,但这里将它包括在内,是因为它涉及将多个数据源中的数据合并为一个结果集,这类似于某些类型的联接。
TRANSFORM 语句用于为记录计算和、平均值、计数或其他类型的聚合总计。 然后它以网格或电子表格格式显示信息,并将数据进行垂直(行)和水平(列)分组。 TRANSFORM 语句的常规形式如下。
TRANSFORM aggregating function
SELECT statement
PIVOT column heading field
例如,如果要生成一个数据表,以便逐年显示每个客户的发票总额。 垂直标题将是客户名称,水平标题将是年份。 可以修改上一个 SQL 语句,以适合转换语句。
TRANSFORM
IIF(Sum([Amount]) IS NULL,'NONE',Sum([Amount]))
AS Total
SELECT [Last Name] & ', ' & [First Name] AS Name
FROM tblCustomers LEFT JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID
GROUP BY [Last Name] & ', ' & [First Name]
PIVOT Format(InvoiceDate, 'yyyy')
IN ('1996','1997','1998','1999','2000')
请注意,聚合函数是 Sum 函数,垂直标题位于 SELECT 语句的 GROUP BY 子句中,水平标题由 PIVOT 关键字 (keyword) 后列出的字段确定。
支持和反馈
有关于 Office VBA 或本文档的疑问或反馈? 请参阅 Office VBA 支持和反馈,获取有关如何接收支持和提供反馈的指南。