我正在使用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并且员工记录只在组合框中显示一次,那么有人可以解释一下这应该如何编写。我不需要在组合框中多次显示员工记录。
这可能会有所帮助:
答案 0 :(得分:1)
当你连接表时,你基本上查询一个结果集,其中包含那些你的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'连接到Emp_Certs表,其中Cert_ID为1,表别名'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 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;
答案 1 :(得分:0)
您应该在OR
子句中使用WHERE
运算符:
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
由于((Emp_Certs.Employee_ID) = [Employees].[Employee_ID])
条件
INNER JOIN
条件也是多余的
答案 2 :(得分:0)
您的查询无效,因为Emp_Certs可能只存储单个值。您无法检查该值是否为1和4.如果您的目标是将多个项目存储到一个字段中,请查看此处:
How to store array or multiple values in one column
最好在不同的领域存储不同的认证。
答案 3 :(得分:0)
您现在选择的是包含员工证书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;
此Edit已经过测试,可以在Access中使用。它返回您请求的结果。使用查询构建器时要记住的关键是您必须两次加入Emp_Certs表。