这不是一个很好的标题(编辑欢迎),但这是一个摘要。我目前的查询工作正常,但可能比我目前使用的更容易。我有一张桌子回答'列' QuestionIDFK,Answer,QuestionnaireIDFK'。表中的数据类似于
QuestionIDFK Answer QuestionnaireIDFK
1 N 1
2 N 1
3 N 1
1 Y 2
2 Y 2
3 Y 2
1 N 3
3 N 3
1 Y 4
3 Y 4
这意味着用户对问卷1和问卷2给出了答案,但没有为问卷3和问卷2提供答案。我需要的是一份问卷ID列表。得到问题2的答案。所以预期的输出是
QuestionnaireWithMissingAnswer2
3
4
我在下面使用此查询,效果很好但我想知道是否更容易:
SELECT distinct a.QuestionnaireIDFK AS QuestionnaireWithMissingAnswer2
FROM Answer a
inner join (
SELECT t.QuestionnaireIDFK,
STUFF(ISNULL((SELECT ', ' + convert(nvarchar, x.QuestionIDFK)
FROM Answer x
WHERE x.QuestionnaireIDFK = t.QuestionnaireIDFK
GROUP BY x.QuestionIDFK
FOR XML PATH (''), TYPE).value('.','VARCHAR(max)'), ''), 1, 2, '')
AS QuesList
FROM Answer t
GROUP BY t.QuestionnaireIDFK) z
ON z.QuestionnaireIDFK = a.QuestionnaireIDFK AND z.QuesList NOT LIKE '%2%'
答案 0 :(得分:2)
您只需将not exists
或group by
与having
条款一起使用:
select QuestionnaireIDFK
from answer
group by QuestionnaireIDFK
having sum(case when QuestionIDFK = 2 then 1 else 0 end) = 0;
这会得到所有没有问题#2的问卷(至少所有问卷都有答案)。
您也可以使用not exists
(或left outer join
):
select distinct QuestionnaireIDFK
from answer
where not exists (select 1
from answer a2
where a.QuestionnaireIDFK = a2.QuestionnaireIDFK and
a2.QuestionIDFK = 2
);
但是,由于distinct
,这不太可能比第一种方法具有更好的性能。
答案 1 :(得分:1)
使用左外连接,连接密钥和答案ID,然后使用where子句过滤掉成功的连接:
select q.*
from Questionnaire q
left join Answer a on a.QuestionnaireIDFK = q.id
and a.QuestionIDFK = 2
where a.QuestionnaireIDFK is null
它使得查询非常简洁有效,因为在连接之后应用的where子句只有在错过连接时才能为true。 "技巧"将条件置于连接条件中,该条件在连接期间进行评估(将条件置于where子句中将有效地使其成为内连接)。
另请注意,您无法获得重复项,因为当我们错过了加入时,主表中只返回了一行。
另请注意,调查问卷根本不需要任何答案才能实现。