[英]SQL query with JOIN involving two criteria from same table
我在 MS Access 中工作,试图解决一个有效的 SQL 语句。 在表单上,我有一个显示员工列表的组合框。 我有一个单独的对话框表单,允许用户在列表框中选择多个项目。 每个项目代表一个认证。 每个员工都可以拥有任意数量和组合的认证。 最终,我只想通过分配适当的 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;
我得到一个空集。 那不是我所期望的。 表 Emp_Certs 显然有几个员工具有认证 1 和 4 的组合。如果我想指出更多的 Cert_ID 并且员工记录只在组合框中显示一次,请有人解释应该如何编写。 我不需要在组合框中多次显示员工记录。
这可能有帮助:
当您连接表时,您基本上会查询一个结果集,该结果集包含来自那些连接表的所有行组合,然后您的 where 子句对其进行操作。 由于您只加入Emp_Certs
表一次并且仅通过 Employee_ID 进行链接,您将获得如下所示的结果集(仅显示两列):
Last_Name Cert_ID
Jones 1
Jones 3
Jones 4
Smith 1
Smith 2
然后您的 where 子句过滤这些行,只接受具有Cert_ID = 1
AND Cert_ID = 4
,这是不可能的,因此您不应获得任何行。
我不确定 Access 是否有限制,但在 SQL Server 中,您至少可以通过两种方式处理它:
1) 两次链接到表,加入每个认证。 表别名“a”连接到 Cert_ID 为 1 的 Emp_Certs 表,表别名“b”连接到 Cert_ID 为 4 的 Emp_Certs 表:
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 没有出现,因为连接条件不允许任何行,除非员工可以链接到表a
和b
):
Last_Name a.Cert_ID b.Cert_ID
Jones 1 4
2)在 where 子句中使用子选择过滤具有这些认证的 id 上的员工 id(看起来Access 2010 支持它):
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;
您应该在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。如果您的目标是将多个项目存储到单个字段中,请查看此处:
您最好在不同领域存储不同的认证。
您现在选择的是包含员工证书 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 中进行测试。 它返回您请求的结果。 使用查询构建器时要记住的关键是您必须两次加入 Emp_Certs 表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.