SQL: выберите данные, которые не имеют отношений в другой таблице - PullRequest
2 голосов
/ 09 марта 2012

Я пишу приложение на C # и использую Access .mdb. У меня есть таблица с сообщениями электронной почты и таблица с отношениями сообщений (каждое сообщение электронной почты может быть назначено нескольким группам работников).

Я хочу получать сообщения из первой таблицы, которые НЕ назначены какой-либо команде, т. Е. Либо не имеют записей во второй таблице, либо содержат пустую запись. Он работает нормально с пустыми записями, но не возвращает строки, которые вообще не имеют этой записи присваивания.

Я использую следующий запрос:

SELECT TOP 10 Mails.* 
FROM Mails INNER JOIN MailAssignments ON Mails.msgId = MailAssignments.msgId 
    WHERE (Mails.msgId <= ?)
    AND
    (Mails.msgId NOT IN (SELECT msgId FROM MailAssignments))
    OR (MailAssignments.forTeam IS NULL)
    OR (MailAssignments.forTeam = '')

UPDATE:

Мне НУЖНО использовать какой-то тип JOIN, потому что при некоторых условиях запрос должен также возвращать строки, имеющие отношение в другой таблице (например, когда кто-то хочет отобразить сообщения из своей команды И неназначенные сообщения).

UPDATE

ОК, я думаю, что могу упростить это, удалив любое назначение из второй таблицы, чтобы мне не нужно было проверять пустые назначения, только те, которые вообще не существуют. Но мне все еще нужно иногда показывать данные, которым присваивается ДАЛЕЕ данные, которые не были назначены. И мне нужно построить один запрос для того, который будет иметь только другие измененные параметры: /

ОБНОВЛЕНИЕ / РЕШЕНИЕ:

Я сделал еще несколько корректировок, но LEFT JOIN в основном помог мне! Спасибо за эту подсказку и всю вашу помощь, ребята!

Ответы [ 3 ]

4 голосов
/ 09 марта 2012

Этого должно быть достаточно:

SELECT TOP 10 Mails.* 
FROM Mails 
    WHERE (Mails.msgId <= ?)
    AND
    (Mails.msgId NOT IN (SELECT msgId FROM MailAssignments))

Читая ваше описание, кажется, что в MailAssignments могут быть строки, связанные с Mails, но команда не назначена (столбец forTeam содержит пустую строку. Это не очень хороший дизайн, но в этом случае используйте это:

SELECT TOP 10 Mails.* 
FROM Mails 
  LEFT JOIN 
     MailAssignments ON Mails.msgId = MailAssignments.msgId
WHERE (Mails.msgId <= ?)
  AND (  (MailAssignments.forTeam IS NULL)
      OR (MailAssignments.forTeam = '')
      )
2 голосов
/ 09 марта 2012

Присоедините Mails к подмножеству MailAssignments, пытаясь сопоставить письма с существующими назначениями (где forTeam <> '') и выбирая те, в которых не было совпадений:

SELECT TOP 10
  Mails.*
FROM Mails
  LEFT JOIN MailAssignments ON Mails.msgId = MailAssignments.msgId
    <b>AND</b> MailAssignments.forTeam <> ''
WHERE Mails.msgId <= ?
  AND MailAssignments.msgId IS NULL /* either no match for this mail at all
                                       or no match with an existing assignment
                                       – so, just no match */
1 голос
/ 09 марта 2012

Поскольку вы использовали объединение, я думаю, вам нужны столбцы из 2-й таблицы, используйте OUTER JOIN вместо INNER JOIN (он возвращает записи в таблице без совпадения в объединении).

Еслиони вам не нужны, я согласен с @ ypercube.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...