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 = 1Cert_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 ab):

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;