简体   繁体   English

如何选择外表中没有匹配的记录(左外连接)

[英]How to select records with no matches in the foreign table (Left outer join)

I have one table that holds my ressources: 我有一个表可以保存我的资源:

Ressource | 资源| Ressource-ID 的ressource-ID

And a table that holds the associations 还有一个包含关联的表

Ressource-ID | Ressource-ID | Employee-ID 员工ID

How to select the ressources of an Employee that are available, ie not in the association table? 如何选择可用的Employee的资源,即不在关联表中?

I've tried this, but it's not working: 我试过这个,但它不起作用:

select r.ress, r.ress_id
FROM Ressource r
LEFT outer JOIN Ressource_Employee_Association a ON r.ress_id = a.ress_id
WHERE a.emp_id = 'ID00163efea66b' and a.ress_id IS NULL

Any ideas? 有任何想法吗?

Thanks Thomas 谢谢托马斯

The WHERE clause is applied after the LEFT JOIN. 在LEFT JOIN之后应用WHERE子句。 This means that you are currently trying to get results where there is NO matching record in Ressource_Employee_Association, but where the emp_id equals 'ID00163efea66b' . 这意味着您当前正在尝试获取Ressource_Employee_Association中没有匹配记录的结果,但emp_id等于'ID00163efea66b'

But if there is no matching record, how can emp_id be anything other than NULL ? 但是如果没有匹配的记录, emp_id怎么可能是除NULL以外的任何东西?

One option is to move part of the WHERE clause into the join... 一种选择是将WHERE子句的一部分移动到连接中......

SELECT
  r.ress, r.ress_id
FROM
  Ressource r
LEFT OUTER JOIN
  Ressource_Employee_Association a
    ON r.ress_id = a.ress_id
    AND a.emp_id = 'ID00163efea66b'
WHERE
  a.ress_id IS NULL

This will list all resources that are not associated to employee 'ID00163efea66b' . 这将列出与员工'ID00163efea66b'无关的所有资源。

EDIT 编辑

Your comment implies that what you want is... 你的评论意味着你想要的是......
- A view listing all employees - 列出所有员工的视图
- For each employee list each resource that they DON'T have - 为每个员工列出他们没有的每个资源

This requires an extra table listing all of your employees. 这需要一个列出所有员工的额外表格。

SELECT
  *
FROM
  Employee
CROSS JOIN
  Ressource
WHERE
  NOT EXISTS (SELECT * FROM Ressource_Employee_Association
               WHERE emp_id  = Employee.id
                 AND ress_id = Ressource.id)

Does this work? 这有用吗?

select r.ress, r.ress_id
from resource r
where not exists 
(
    select 1 from ressource_emplyee_association a 
    where a.emp_id = '...' and a.ress_id = r.ress_id
)

EDIT 编辑
Before that I had the following, but changed it according to the comments below: 在此之前,我有以下内容,但根据以下评论进行了更改:

select r.ress, r.ress_id
from resource r
where not exists 
(
    select top 1 1 from ressource_emplyee_association a 
    where a.emp_id = '...' and a.ress_id = r.ress_id
)
SELECT * 
  FROM Ressource
 WHERE ress_id IN (
                   SELECT ress_id, 
                     FROM Ressource 
                   MINUS
                   SELECT ress_id
                     FROM Ressource_Employee_Association 
                    WHERE emp_id = 'ID00163efea66b'
                  );

After writing my above comments, and looking at the proposed solutions: I think I've got some more understanding of what you are trying to do. 在写完我的上述评论之后,看看提出的解决方案:我想我已经对你要做的事情有了更多的了解。

Assuming you have unlimited quantity of resources in your resources table, you want to select the un-assigned resources per employee (based on their non-existence for any specific employee in the resource association table). 假设资源表中有无限数量的资源,您希望为每个员工选择未分配的资源(基于资源关联表中任何特定员工的不存在)。

In order to accomplish this (and get a comprehensive list of employees) you'll need a 3rd table, in order to reference the complete list of employees. 为了实现这一目标(并获得全面的员工列表),您需要第3个表格,以便参考完整的员工列表。 You'll also need to CROSS JOIN all of the resources onto the list of employees (assuming every employee has access to every resource), then you LEFT JOIN ( LEFT OUTER JOIN whatever) your association list onto the query where the resource_id and employee_id match the resource_id in the resources table, and the employee_id in the employees table (respectively). 您还需要将所有资源CROSS JOIN连接到员工列表中(假设每个员工都可以访问每个资源),然后将您的关联列表LEFT JOINLEFT OUTER JOIN )放到resource_idemployee_id匹配的查询中在resource_idresources表和employee_idemployees (分别)表。 THEN you add your where clause that filters out all the records that assign an employee to a resource. 然后,添加where子句,过滤掉将员工分配给资源的所有记录。 This leaves you with the resources that are available to the employee, which they also do not have signed out. 这将为您提供员工可用的资源,这些资源也未注销。 This is convoluted to say, so hopefully the query sheds more light: 这是令人费解的,所以希望这个问题可以解释得更多:

SELECT e.employee_id, e.employee, r.res_id, r.res

FROM employees e
CROSS JOIN resources r
LEFT JOIN assigned_resources ar
    ON ar.employee_id = e.employee_id AND r.res_id = ar.res_id

WHERE ar.res_id IS NULL

If you don't have an employees table, you can accomplish the same by using the assigned resources table, but you will be limited to selecting employees who already have some resources allocated. 如果您没有employees表,则可以使用分配的资源表来完成相同的操作,但您将仅限于选择已分配资源的员工。 You'll need to add a GROUP BY query because of the possible existence of multiple employee definitions in the association table. 您需要添加GROUP BY查询,因为关联表中可能存在多个员工定义。 Here's what that query would look like: 这是查询的样子:

SELECT e.employee_id, r.res_id, r.res

FROM assigned_resources e
CROSS JOIN resources r
LEFT JOIN assigned_resources ar
    ON ar.employee_id = e.employee_id AND r.res_id = ar.res_id

WHERE ar.res_id IS NULL

GROUP BY e.employee_id, r.res_id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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