SQL 包含来自相同 table 的两个条件的 JOIN 查询
SQL query with JOIN involving two criteria from same table
我正在 MS Access 中工作,试图找出一个有效的 SQL 语句。在一个表单上,我有一个显示员工列表的组合框。我有一个单独的对话框表单,允许用户 select 列表框中的多个项目。每一项都代表一个认证。每个员工都可以拥有任意数量和组合的认证。最后,我只想通过分配适当的 SQL 语句来更新组合框的 RowSource 属性 以反映新的过滤数据。
如果我想过滤员工组合框中的列表,我使用这个 SQL 语句:
SELECT
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name
FROM
Employees
INNER JOIN
Emp_Certs ON Employees.Employee_ID = Emp_Certs.Employee_ID
WHERE
(((Employees.Active_Member) = Yes)
AND ((Emp_Certs.Employee_ID) = [Employees].[Employee_ID])
AND ((Emp_Certs.Cert_ID) = 1))
ORDER BY
Employees.Last_Name;
如果我 运行 此查询有效,因为我只为 Emp_Certs.Cert_ID
分配了一个值。但是当我这样添加另一个时:
SELECT
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name
FROM
Employees
INNER JOIN
Emp_Certs ON Employees.Employee_ID = Emp_Certs.Employee_ID
WHERE
(((Employees.Active_Member) = Yes)
AND ((Emp_Certs.Employee_ID) = [Employees].[Employee_ID])
AND ((Emp_Certs.Cert_ID) = 1)
AND ((Emp_Certs.Cert_ID) = 4))
ORDER BY Employees.Last_Name;
我得到一个空集。那不是我所期望的。 table Emp_Certs 显然有几名员工同时拥有认证 1 和 4。
如果我想指示更多 Cert_ID 并让员工记录在组合框中只显示一次,请有人解释一下应该如何编写。我不需要在组合框中多次显示员工记录。
这可能有帮助:
您应该在 WHERE
子句中使用 OR
运算符:
WHERE
(((Employees.Active_Member) = Yes)
AND ((Emp_Certs.Employee_ID) = [Employees].[Employee_ID])
AND ( Emp_Certs.Cert_ID = 1 OR
Emp_Certs.Cert_ID = 4 )
ORDER BY Employees.Last_Name;
因为 Emp_Certs.Cert_ID = 1 and Emp_Certs.Cert_ID = 4
总是 FALSE
此外,由于 INNER JOIN
条件
,((Emp_Certs.Employee_ID) = [Employees].[Employee_ID])
条件是多余的
您的查询无效,因为 Emp_Certs 可能只存储了一个值。您无法检查该值是否同时为 1 和 4。如果您的目标是将多个项目存储到一个字段中,请看这里:
How to store array or multiple values in one column
您最好将不同的证书存储在不同的字段中。
您现在选择的是同时包含员工证书 1 和 4 的行。您需要一个查询,该查询将在类似这样的访问中实现...
SELECT DISTINCT Employees.Employee_ID, Employees.Last_Name, Employee.First_Name
FROM Emp_Certs AS a
INNER JOIN (Emp_Certs INNER JOIN Employees ON Emp_Certs.Employee_Id = Employees.Employee_ID) ON a.Employee_ID = Employees.Employee_ID
WHERE (((Emp_Certs.CertId)=1) AND ((a.CertId)=4) AND ((Employees.Active_Member)=Yes))
ORDER BY Employee.Last;
此编辑经测试可在 Access 中使用。它 returns 您要求的结果。使用查询生成器时要记住的关键是你必须加入 Emp_Certs table 两次。
当您加入 tables 时,您基本上查询了一个结果集,其中包含那些加入的 tables 中的所有行组合,然后您的 where 子句将在其中运行。由于您仅加入 Emp_Certs
table 一次并且仅通过 Employee_ID 加入 link,因此您得到的结果集如下所示(仅显示两列):
Last_Name Cert_ID
Jones 1
Jones 3
Jones 4
Smith 1
Smith 2
您的 where 子句然后过滤这些行,只接受具有 Cert_ID = 1
和 Cert_ID = 4
的行,这是不可能的,因此您不应该得到任何行。
我不确定 Access 是否有限制,但在 SQL 服务器中,您至少可以通过两种方式处理它:
1) Link 到 table 两次,加入每个认证。 Table 别名 'a' 连接到 Emp_Certs table 其中 Cert_ID 是 1 而 table 别名 'b' 连接到 Emp_Certs table 其中 Cert_ID 是 4:
SELECT
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name
FROM
Employees
INNER JOIN
Emp_Certs a ON Employees.Employee_ID = a.Employee_ID AND a.Cert_ID = 1
INNER JOIN
Emp_Certs b ON Employees.Employee_ID = b.Employee_ID AND b.Cert_ID = 4
WHERE
Employees.Active_Member = Yes
ORDER BY Employees.Last_Name;
这为您提供了一个如下所示的结果集(Smith 未出现,因为联接条件不允许任何行,除非员工可以 link 到 table a
和 b
):
Last_Name a.Cert_ID b.Cert_ID
Jones 1 4
2) 在 where 子句中使用子选择来过滤具有这些认证的 ids 上的员工 id(看起来像 Access 2010 supports it):
SELECT
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name
FROM
Employees
WHERE
Active_Member = Yes
AND Employee_ID in (SELECT Employee_ID FROM Emp_Certs WHERE Cert_ID = 1)
AND Employee_ID in (SELECT Employee_ID FROM Emp_Certs WHERE Cert_ID = 4)
ORDER BY Employees.Last_Name;
我正在 MS Access 中工作,试图找出一个有效的 SQL 语句。在一个表单上,我有一个显示员工列表的组合框。我有一个单独的对话框表单,允许用户 select 列表框中的多个项目。每一项都代表一个认证。每个员工都可以拥有任意数量和组合的认证。最后,我只想通过分配适当的 SQL 语句来更新组合框的 RowSource 属性 以反映新的过滤数据。
如果我想过滤员工组合框中的列表,我使用这个 SQL 语句:
SELECT
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name
FROM
Employees
INNER JOIN
Emp_Certs ON Employees.Employee_ID = Emp_Certs.Employee_ID
WHERE
(((Employees.Active_Member) = Yes)
AND ((Emp_Certs.Employee_ID) = [Employees].[Employee_ID])
AND ((Emp_Certs.Cert_ID) = 1))
ORDER BY
Employees.Last_Name;
如果我 运行 此查询有效,因为我只为 Emp_Certs.Cert_ID
分配了一个值。但是当我这样添加另一个时:
SELECT
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name
FROM
Employees
INNER JOIN
Emp_Certs ON Employees.Employee_ID = Emp_Certs.Employee_ID
WHERE
(((Employees.Active_Member) = Yes)
AND ((Emp_Certs.Employee_ID) = [Employees].[Employee_ID])
AND ((Emp_Certs.Cert_ID) = 1)
AND ((Emp_Certs.Cert_ID) = 4))
ORDER BY Employees.Last_Name;
我得到一个空集。那不是我所期望的。 table Emp_Certs 显然有几名员工同时拥有认证 1 和 4。 如果我想指示更多 Cert_ID 并让员工记录在组合框中只显示一次,请有人解释一下应该如何编写。我不需要在组合框中多次显示员工记录。
这可能有帮助:
您应该在 WHERE
子句中使用 OR
运算符:
WHERE
(((Employees.Active_Member) = Yes)
AND ((Emp_Certs.Employee_ID) = [Employees].[Employee_ID])
AND ( Emp_Certs.Cert_ID = 1 OR
Emp_Certs.Cert_ID = 4 )
ORDER BY Employees.Last_Name;
因为 Emp_Certs.Cert_ID = 1 and Emp_Certs.Cert_ID = 4
总是 FALSE
此外,由于 INNER JOIN
条件
((Emp_Certs.Employee_ID) = [Employees].[Employee_ID])
条件是多余的
您的查询无效,因为 Emp_Certs 可能只存储了一个值。您无法检查该值是否同时为 1 和 4。如果您的目标是将多个项目存储到一个字段中,请看这里:
How to store array or multiple values in one column
您最好将不同的证书存储在不同的字段中。
您现在选择的是同时包含员工证书 1 和 4 的行。您需要一个查询,该查询将在类似这样的访问中实现...
SELECT DISTINCT Employees.Employee_ID, Employees.Last_Name, Employee.First_Name
FROM Emp_Certs AS a
INNER JOIN (Emp_Certs INNER JOIN Employees ON Emp_Certs.Employee_Id = Employees.Employee_ID) ON a.Employee_ID = Employees.Employee_ID
WHERE (((Emp_Certs.CertId)=1) AND ((a.CertId)=4) AND ((Employees.Active_Member)=Yes))
ORDER BY Employee.Last;
此编辑经测试可在 Access 中使用。它 returns 您要求的结果。使用查询生成器时要记住的关键是你必须加入 Emp_Certs table 两次。
当您加入 tables 时,您基本上查询了一个结果集,其中包含那些加入的 tables 中的所有行组合,然后您的 where 子句将在其中运行。由于您仅加入 Emp_Certs
table 一次并且仅通过 Employee_ID 加入 link,因此您得到的结果集如下所示(仅显示两列):
Last_Name Cert_ID
Jones 1
Jones 3
Jones 4
Smith 1
Smith 2
您的 where 子句然后过滤这些行,只接受具有 Cert_ID = 1
和 Cert_ID = 4
的行,这是不可能的,因此您不应该得到任何行。
我不确定 Access 是否有限制,但在 SQL 服务器中,您至少可以通过两种方式处理它:
1) Link 到 table 两次,加入每个认证。 Table 别名 'a' 连接到 Emp_Certs table 其中 Cert_ID 是 1 而 table 别名 'b' 连接到 Emp_Certs table 其中 Cert_ID 是 4:
SELECT
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name
FROM
Employees
INNER JOIN
Emp_Certs a ON Employees.Employee_ID = a.Employee_ID AND a.Cert_ID = 1
INNER JOIN
Emp_Certs b ON Employees.Employee_ID = b.Employee_ID AND b.Cert_ID = 4
WHERE
Employees.Active_Member = Yes
ORDER BY Employees.Last_Name;
这为您提供了一个如下所示的结果集(Smith 未出现,因为联接条件不允许任何行,除非员工可以 link 到 table a
和 b
):
Last_Name a.Cert_ID b.Cert_ID
Jones 1 4
2) 在 where 子句中使用子选择来过滤具有这些认证的 ids 上的员工 id(看起来像 Access 2010 supports it):
SELECT
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name
FROM
Employees
WHERE
Active_Member = Yes
AND Employee_ID in (SELECT Employee_ID FROM Emp_Certs WHERE Cert_ID = 1)
AND Employee_ID in (SELECT Employee_ID FROM Emp_Certs WHERE Cert_ID = 4)
ORDER BY Employees.Last_Name;