基于 CASE 语句对结果进行分组?

Grouping results based on CASE statement?

我正在使用一个 table 来存储对人们进行的问卷调查的结果。每个问题及其结果都存储为单独的记录,如下所示。我写了一个 CASE 语句,它根据人们对某些问题的回答创建一个简单的 1/0 标志。我的结果看起来像这样。

PersonID    Question       Answer       Flag
---------------------------------------------
1001        Question 1     yes          1
1001        Question 2     3            0
1001        Question 3     1 or more    1
1234        Question 1     no           0
1234        Question 2     2            0
1234        Question 3     none         0

我现在的问题是,即使一个人只有一个标记的回答,我也需要标记他们的整个问卷。我一直在寻找这个问题的其他例子—— 正在处理几乎完全相同的事情,但我不一定想 实际上 对我的结果进行分组,因为我仍然希望能够看到各个问题的标记(“哦,这个人的问卷被标记了,让我们看看它是针对哪个问题以及他们的回答是什么”)。我知道这可能不是最有效的方法,但我希望结果如下所示:

PersonID    Question       Answer       Flag    Overall
--------------------------------------------------------
1001        Question 1     yes          1         1
1001        Question 2     3            0         1
1001        Question 3     1 or more    1         1
1234        Question 1     no           0         0
1234        Question 2     2            0         0
1234        Question 3     none         0         0

这是我查询的地方。它可以很好地标记单个问题,但我不确定要采取什么步骤才能根据单个答案标记整个问卷。我应该看什么样的 logic/syntax?

SELECT
    PersonID,
    QuestionDescription as Question,
    ResultValue as Answer,
    (CASE
        WHEN (QuestionDescription LIKE '%ion 1%' AND ResultValue = 'yes') THEN 1
        WHEN (QuestionDescription LIKE '%ion 2%' AND ResultValue >= 5) THEN 1
        WHEN (QuestionDescription LIKE '%ion 3%' AND ResultValue = '1 or more') THEN 1
        ELSE 0
     END) as Flag

FROM Questionnaire

ORDER BY PersonID, QuestionDescription

在最简单的情况下,您可以将此人分区内的标志相加,看看它们的总和是否为 0:

WITH x AS
(
  SELECT
    PersonID,
    QuestionDescription as Question,
    ResultValue as Answer,
    CASE
        WHEN (QuestionDescription LIKE '%ion 1%' AND ResultValue = 'yes') THEN 1
        WHEN (QuestionDescription LIKE '%ion 2%' AND ResultValue >= 5) THEN 1
        WHEN (QuestionDescription LIKE '%ion 3%' AND ResultValue = '1 or more') THEN 1
        ELSE 0
     END as Flag
  FROM Questionnaire
)

SELECT 
  *,
  CASE WHEN SUM(Flag) OVER(PARTITION BY PersonID) > 0 THEN 1 ELSE 0 END as Overall
FROM
  x

SUM(...) OVER(...)有点像做下面的事情:

WITH x AS ( 
  --your existing query here
)

SELECT *, CASE WHEN SumFlag > 0 THEN 1 ELSE 0 END as OVerall
FROM
  x
  INNER JOIN
  (SELECT PersonId, SUM(Flag) AS SumFlag FROM X GROUP BY PersonId) y ON x.PersonId = y.PersonId

即SUM OVER 对 PersonId、Sum 进行分组,然后自动将结果连接回分组的每一行 (PersonId) - 它们非常强大和有用,这些 window 函数

如果您不能继续使用 window 函数 (SUM OVER) 方法,后一种形式(单独的查询组并重新加入)也可以工作 - 这类似于 datarocker 指向的内容在他们的回答中