繁体   English   中英

带有 JOIN 的 SQL 查询涉及同一表中的两个条件

[英]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 没有出现,因为连接条件不允许任何行,除非员工可以链接到表ab ):

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM