sql-server-2008 - SQL Join 到具有 3个可能情况的表: 表可以没有记录,匹配 1或者更多,记录或者要求找到的所有记录都匹配

  显示原文与译文双语对照的内容

我有 2张表格:


 Questions table with Question ID

零件表:


 Question ID
 Part ID
 BAllPartsRequired

用户将选择部分( 或者选择无),根据所选内容,将显示某些问题。

我想将 2个表的3个表( 1个) 放在一起,但在个查询中都做。 我可以编写每个scenerio单独的( 编辑我认为我可以不能在那里工作,它需要所有在部件表中被选择的工作。),但是无法找到如何在 1查询( 我以前做过类似的事情但不能记住) 中获取它们。

  1. 如果该问题的部件表中不存在任何部件,则

  2. 如果部件表返回问题中所选的任何部分都存在( 例如 ) 。 用户选择 1部分和 5部分与该问题相关联,那么问题将匹配并被返回。 BAllPartsRequired = false

  3. 如果用户选择部分,所有部分都与问题关联,问题是 returend,但是如果不是所有部分都是由用户选择的问题不是 returend ( 例如 ) 。 用户选择 3部分,表中有 4个部分,但用户不会看到问题,但如果用户选择了所有 4部分。 BAllPartsRequired = true

虽然这是个高级的SQL程序员,但是我知道在 1查询之前,我已经完成了这个工作,但我如何让它在where语句中运行。

示例数据:


Question Form Association: 
NFormAssociationID NQuestionID FormType 
1 1 PAEdit 
2 2 PAEdit 
3 3 PAEdit 
4 4 PAEdit 




Question Part Form Association Table: 
ID NFormAssociationID PartNumber BAllPartsRequired
1 1 1 0
2 2 2 1
3 2 3 1

在没有添加新零件表的情况下查询:


Select ROW_NUMBER() OVER(ORDER BY QL.NOrderBy) AS RowNumber,
QL.NQuestionID, QL.FieldName, QL.Question, QL.BRequired, QFL.FormFieldType, QFL.SingleMultipleSM, 
QFL.CSSStyle
FROM dbo.QuestionFormAssociation QA WITH (NOLOCK)
INNER JOIN dbo.QuestionLookup QL WITH (NOLOCK) ON QA.NQuestionID = QL.NQuestionID
INNER JOIN dbo.QuestionFieldTypeLookup QFL WITH (NOLOCK) ON QL.NFieldTypeID = QFL.NFieldTypeID
WHERE QA.BActive = 1 AND QL.BActive = 1 AND QFL.BActive=1
AND QA.FormType = 'PAEdit'
ORDER BY QL.NOrderBy

使用新表的简单查询


Select ID
 FROM dbo.QuestionPartFormAssociation 
 WHERE BAllPartsRequired = 1 
 AND PartNumber IN ('1', '2') --'1', '2', '3') 

时间: 作者:

听起来你在试图找到一些符合标准的问题。

在这个sitatuion中,最好首先对问题级别进行总结,然后将逻辑应用到这些概要。 以下是一个示例:


select q.questionid
from (select q.questionid,
 max(case when qp.questionid is null then 1 else 0 end) as HasNoParts,
 sum(case when qp.partid in (<user parts>) then 1 else 0 end) as NumUserParts,
 count(qp.questionid) as NumParts,
 max(qp.AllPartsRequired) as AreAllPartsRequired
 from question q left outer join
 questionpart qp
 on q.questionid = qp.questionid
 group by q.questionid
 ) q
 where HasNoParts = 1 or -- condition 1
 AreAllPartsRequired = 0 and NumUserParts> 0 or -- condition 2
 AreAllPartsRequired = 1 and NmUserParts = NumParts -- condition 3

我已经简化了表格和列名,使逻辑更加清晰。

从OP的完整回答中更新:


Select ROW_NUMBER() OVER(ORDER BY QL.NOrderBy) AS RowNumber,
QL.NQuestionID, QL.FieldName, QL.Question, QL.BRequired, QFL.FormFieldType, QFL.SingleMultipleSM, 
QFL.CSSStyle
FROM dbo.QuestionFormAssociation QA WITH (NOLOCK)
INNER JOIN dbo.QuestionLookup QL WITH (NOLOCK) ON QA.NQuestionID = QL.NQuestionID
INNER JOIN dbo.QuestionFieldTypeLookup QFL WITH (NOLOCK) ON QL.NFieldTypeID = QFL.NFieldTypeID
INNER JOIN (
 select q.NFormAssociationID,
 max(case when qp.NFormAssociationID is null then 1 else 0 end) as HasNoParts,
 sum(case when qp.PartNumber in ('1','2','3') then 1 else 0 end) as NumUserParts,
 count(qp.NFormAssociationID) as NumParts, 
 qp.BAllPartsRequired
 from QuestionFormAssociation q 
 left outer join QuestionPartFormAssociation qp on q.NFormAssociationID = qp.NFormAssociationID 
 AND QP.BActive = 1 
 WHERE Q.FormType = 'PAEdit' 
 AND Q.BActive = 1 
 group by q.NFormAssociationID, qp.BAllPartsRequired

) QSUB ON QA.NFormAssociationID = QSUB.NFormAssociationID
WHERE QA.BActive = 1 AND QL.BActive = 1 AND QFL.BActive=1
AND (
 QSUB.HasNoParts = 1 -- condition 1
 OR (QSUB.BAllPartsRequired = 0 and QSUB.NumUserParts> 0) -- condition 2
 OR (QSUB.BAllPartsRequired = 1 and QSUB.NumUserParts = QSUB.NumParts) -- condition 3
)
ORDER BY QL.NOrderBy

作者:
...