Как выбрать записи без совпадений во внешней таблице (левое внешнее соединение) - PullRequest
1 голос
/ 12 января 2012

У меня есть одна таблица, в которой хранятся мои ресурсы:

Ресурс | Ressource-ID

И таблица, которая содержит ассоциации

Ressource-ID | Сотрудник-ID

Как выбрать доступные ресурсы сотрудника, т. Е. Нет в таблице сопоставления?

Я пробовал это, но это не работает:

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

Есть идеи?

Спасибо Томас

Ответы [ 4 ]

1 голос
/ 12 января 2012

После написания моих комментариев выше и рассмотрения предлагаемых решений: я думаю, что у меня появилось больше понимания того, что вы пытаетесь сделать.

Предполагая, что в вашей таблице ресурсов имеется неограниченное количество ресурсов, вы хотите выбрать неназначенные ресурсы для каждого сотрудника (на основе их отсутствия для какого-либо конкретного сотрудника в таблице ассоциации ресурсов).

Чтобы выполнить это (и получить исчерпывающий список сотрудников), вам понадобится третья таблица для ссылки на полный список сотрудников. Вам также потребуется CROSS JOIN всех ресурсов в списке сотрудников (при условии, что каждый сотрудник имеет доступ к каждому ресурсу), а затем вы LEFT JOIN (LEFT OUTER JOIN независимо от того) ваш список ассоциаций на запрос, где resource_id и employee_id соответствуют resource_id в таблице resources и employee_id в таблице employees (соответственно). Затем вы добавляете предложение where, которое отфильтровывает все записи, которые назначают сотрудника для ресурса. Это оставляет вас с ресурсами, которые доступны сотруднику, которые они также не подписали. Это запутанно, так что, надеюсь, запрос прольет больше света:

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

Если у вас нет таблицы employees, вы можете сделать то же самое, используя назначенную таблицу ресурсов, но вы будете ограничены выбором сотрудников, которым уже выделены некоторые ресурсы. Вам нужно будет добавить запрос GROUP BY из-за возможного существования нескольких определений сотрудников в таблице связей. Вот как будет выглядеть этот запрос:

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
1 голос
/ 12 января 2012

Это работает?

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
До этого у меня было следующее, но я изменил его в соответствии с комментариями ниже:

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
)
1 голос
/ 12 января 2012
SELECT * 
  FROM Ressource
 WHERE ress_id IN (
                   SELECT ress_id, 
                     FROM Ressource 
                   MINUS
                   SELECT ress_id
                     FROM Ressource_Employee_Association 
                    WHERE emp_id = 'ID00163efea66b'
                  );
1 голос
/ 12 января 2012

Предложение WHERE применяется после LEFT JOIN.Это означает, что вы в настоящее время пытаетесь получить результаты, если в Ressource_Employee_Association НЕТ совпадающей записи, но где emp_id равно 'ID00163efea66b'.

Но если нет соответствующей записи, как может emp_idчто-нибудь кроме NULL?

Один из вариантов - переместить часть предложения 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

В этом списке будут перечислены все ресурсы, которые не связаны с сотрудником 'ID00163efea66b'.

РЕДАКТИРОВАТЬ

Ваш комментарий подразумевает, что вы хотите ...
- Просмотр списка всех сотрудников
- Для каждого списка сотрудниковкаждый ресурс, который они НЕ имеют

Для этого требуется дополнительная таблица со списком всех ваших сотрудников.

SELECT
  *
FROM
  Employee
CROSS JOIN
  Ressource
WHERE
  NOT EXISTS (SELECT * FROM Ressource_Employee_Association
               WHERE emp_id  = Employee.id
                 AND ress_id = Ressource.id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...