首页 文章

使用JOIN的SQL查询涉及来自同一个表的两个条件

提问于
浏览
2

我正在使用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并且员工记录只在组合框中显示一次,有人可以解释如何写这个 . 我不需要在组合框中多次显示员工记录 .

这可能有所帮助:

enter image description here

4 回答

  • 1

    您应该在 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]) 条件也是冗余的

  • 0

    您的查询无效,因为Emp_Certs可能只存储单个值 . 您无法检查该值是否为1和4.如果您的目标是将多个项目存储到单个字段中,请查看此处:

    How to store array or multiple values in one column

    您可能最好在不同的领域存储不同的认证 .

  • 0

    当你连接表时,你基本上查询一个结果集,其中包含那些你的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;
    

    这给你一个看起来像这样的结果集(史密斯不允许任何行,除非员工可以链接到表 ab ):

    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;
    
  • 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表 .

相关问题