запрос t-sql, который возвращает отсутствующие записи

У меня есть запрос (ContactFormTypesRequired), который возвращает ContactID и FormTypeID с использованием связанных таблиц, которые не показаны ниже. Это список типов форм, которые каждый контакт должен иметь отношение к себе как к форме.

Мне нужен запрос, который возвращает контакты, у которых нет одной или нескольких связанных форм FormTypes, указанных в приведенном выше запросе.

Я пробовал левое внешнее соединение из формы в ContactsFormTypesRequired для FormTypeID, но результаты не учитывают типы форм, которые должен иметь каждый конкретный контакт.

Пожалуйста, дай мне знать, если возникнут какие-либо вопросы.

Заранее благодарим вас за любые предложения.

схема


person cResults    schedule 28.12.2012    source источник
comment
Пожалуйста, опубликуйте запрос, который вы пробовали.   -  person Mahmoud Gamal    schedule 28.12.2012
comment
Я благодарен за вклад каждого. ContactFormTypesRequired — это в основном запрос, который переходит от соединения Contact к соединению ContactType, к m2m ContactTypeFormType и к FormType. Если бы я заявил об этом в первую очередь, стали бы вы искать контакты, в которых отсутствуют указанные типы форм, используя ContactFormTypesRequired и ваш ответ ниже. ИЛИ есть лучший способ? Простите меня за то, что я не дал этой детали в исходном вопросе.   -  person cResults    schedule 30.12.2012


Ответы (3)


Я пишу запрос таким образом. Сначала это начинается с вашего запроса, чтобы получить необходимые формы в качестве CTE, затем перекрестно объединяет их с контактами, чтобы получить каждую необходимую комбинацию, прежде чем оставить присоединение к фактическим формам.

with NeededForms (<yourqueryhere>)
select distinct c.*
from Contact c cross join
     NeededForms nf left outer join
     Form F
     on nf.FormTypeId = f.FormTypeId left outer join
     ContactForm cf
     on c.ContactId = cf.ContactId and
        f.FormId = cf.FormId
where cf.FormId is null

Я делаю это так, чтобы вы могли ответить на запрос о том, какие формы отсутствуют, очень похожим запросом:

with NeededForms (<yourqueryhere>)
select c.*, nf.FormTypeId
from Contact c cross join
     NeededForms nf left outer join
     Form F
     on nf.FormTypeId = f.FormTypeId left outer join
     ContactForm cf
     on c.ContactId = cf.ContactId and
        f.FormId = cf.FormId
where cf.FormId is null
person Gordon Linoff    schedule 28.12.2012
comment
ContactFormTypesRequired не возвращает FormID, он возвращает FormTypeID. Например, тип формы может быть приложением. Контакт может иметь несколько экземпляров приложения, каждый из которых будет представлен идентификатором FormID. Могу ли я просто использовать FormTypeID вместо FormID в вашем запросе, чтобы найти контакты, для которых ContactType требует, чтобы у них было приложение, но у них его нет? - person cResults; 30.12.2012
comment
Я пересмотрел запрос на основе улучшенного описания модели данных. - person Gordon Linoff; 30.12.2012
comment
Вы намеревались связать NeededForms с Forms по FormID = FormTypeID? Это не сработает, как есть, тем не менее, я вижу, как вы к этому подходите. Я попробую. Спасибо. - person cResults; 02.01.2013
comment
@GordonLinoff Я пробовал ваш второй запрос выше, но мне трудно сопоставить ваши псевдонимы с объявленными таблицами, запросами и т. д. Я предполагаю, что c каким-то образом должен ссылаться на контакт, а f каким-то образом ссылается на форму . Не могли бы вы помочь? - person cResults; 03.01.2013
comment
@GordonLinoff Спасибо за быстрый ответ на мой комментарий. Когда я применил изменения, запрос вернул все контакты в системе, а не отсутствующие идентификаторы FormTypeID. Я придумал комбинацию запросов, которые работают, и разместил их в качестве ответа. Я благодарен за ваше взаимодействие в этом посте. - person cResults; 04.01.2013

Попробуйте этот простой запрос, используя предложение NOT IN:

SELECT * FROM Contact
WHERE ContactID IN 
(SELECT ContactID FROM ContactForm 
INNER JOIN FORM ON ContactForm.FormID=Form.FormID
WHERE FormTypeID=@FormTypeID)
person Atheer Mostafa    schedule 28.12.2012
comment
Это находит только Contacts без Form вообще. Он не находит Contact, у которых есть хотя бы один Form, но отсутствуют один или несколько дополнительных обязательных FormType, найденных представлением ContactFormTypesRequired. - person ErikE; 29.12.2012
comment
Если в вашем запросе нет ссылки на представление ContactFormTypesRequired, независимо от того, сколько правок вы сделаете, как долго будет выполняться запрос или насколько громоздкий набор строк будет получен, это будет неправильный ответ. - person ErikE; 29.12.2012
comment
@ErikE, успокойся, да, я снова прочитал вопрос cResults, я думаю, что неправильно понял часть вопроса, связанную с ContactFormTypesRequired , я напишу его снова в новом ответе позже и удалю его после рабочего дня. - person Atheer Mostafa; 29.12.2012
comment
Так ты думаешь, я слишком остро реагирую или схожу с ума или что-то в этом роде? - person ErikE; 29.12.2012

Я создал ContactFormTypeExist:

SELECT DISTINCT Contact.ContactID, Form.FormTypeID
FROM Contact 
    INNER JOIN ContactForm 
        ON Contact.ContactID = ContactForm.ContactID 
    INNER JOIN Form 
        ON ContactForm.FormID = Form.FormID

Затем присоединил ContactFormTypesRequired, описанный в вопросе выше, к ContactFormTypeExist с внешним соединением, чтобы дать мне идентификаторы ConactID, в которых отсутствуют связанные идентификаторы FormTypeID:

SELECT ContactFormTypesRequired.ConactID
FROM ContactFormTypeExist 
    RIGHT JOIN ContactFormTypesRequired 
        ON (ContactFormTypeExist.FormTypeID = ContactFormTypesRequired.FormTypeID) 
            AND (ContactFormTypeExist.ConactID = ContactFormTypesRequired.ConactID)
WHERE (((ContactFormTypeExist.ConactID) Is Null));

Это возвращает все ContactID для контактов, отсутствующие FormTypes, требуемые их ContactType.

person cResults    schedule 03.01.2013