从调查答案矩阵中获取响应计数

时间:2015-03-02 16:57:25

标签: sql-server pivot

我有一张表格,可以存储幸福问题的答案。结构是:

Wellbeing(WellbeingId, WellbeingDate, Q1, Q2, Q3, Q4, Q5, Q6, Q7...)

+------------+---------------+----+----+----+
|WellbeingId | WellbeingDate | Q1 | Q2 | Q3 |...
+============+===============+====+====+====+
|1           | 01/01/2015    | 1  | 1  | 5  |
+------------+---------------+----+----+----+
|2           | 10/01/2015    | 3  | 3  | 2  |
+------------+---------------+----+----+----+
|3           | 18/01/2015    | 2  | 4  | 1  |
+------------+---------------+----+----+----+

WellbeingResponses(ResponseId,ResponseText)

+-----------+---------------------+
|ResponseId | ResponseText        |
+===========+=====================+
|1          | 'None of the Time'  |
+-----------+---------------------+
|2          | 'Rarely'            |
+-----------+---------------------+
|3          | 'Sometimes'         |
+-----------+---------------------+
|4          | 'Most of the time'  |
+-----------+---------------------+
|5          | 'All of the time'   |
+-----------+---------------------+

每个Q列的值介于15之间。这些值链接到相关文本的另一个表(即1 =不是很多,5 =一直等等。)

我想从SQL Server获取数据作为每个可能响应值的总计数,如下所示:

+-------------------+----------+----------+-------------+
|Response           | Q1 Total | Q2 Total | Q3 Total ...|
+===================+==========+==========+=============+
|'None of the Time' | 500      | 256      | 546         |
+-------------------+----------+----------+-------------+
|'Rarely'           | 500      | 256      | 546         |
+-------------------+----------+----------+-------------+
|'Sometimes'        | 500      | 256      | 546         |
+-------------------+----------+----------+-------------+

我已经尝试选择数据的各个位并使用union all,但只是将数据堆叠为7" Q"中的每一个的5个值中的每一个的计数。列,也尝试调整我在某个地方找到的数据透视查询但是在尝试使用动态数据从WellbeingResponses表中选择它们的列时无法解决这个问题。

非常感谢任何帮助。

编辑:添加了福利回复表。

1 个答案:

答案 0 :(得分:2)

你的Wellbeing表格有点混乱。我真的建议重写此表以进行规范化,这样您就可以避免执行多个连接,甚至无需对数据进行取消以获得所需的结果。

由于您当前的表是非规范化的,因此您必须转换数据以使其可用,然后将其聚合,最后将其重新转换为您最终的期望结果。这会有点乱,但有几种方法可以做到这一点。

您可以获得结果的一种方法是取消wellbeing表的格式化,以便对数据进行规范化。由于您使用的是SQL Server,因此可以使用UNPIVOT功能,或者根据版本,您可以使用CROSS APPLY。将多列转换为多行的代码将是:

select col, value
from wellbeing
cross apply
(
  select 'Q1', Q1 union all
  select 'Q2', Q2 union all
  select 'Q3', Q3
) c (col, value);

Demo。这将以以下格式获取您的数据:

| COL | VALUE |
|-----|-------|
|  Q1 |     1 |
|  Q2 |     1 |
|  Q3 |     5 |
|  Q1 |     3 |
|  Q2 |     3 |

现在可以使用其他表轻松加入数据:

select r.ResponseText, d.col
from WellbeingResponses r
left join
(
  select col, value
  from wellbeing
  cross apply
  (
    select 'Q1', Q1 union all
    select 'Q2', Q2 union all
    select 'Q3', Q3
  ) c (col, value)
) d
  on r.responseid = d.value

Demo。获得每个问题和响应的列表后,您可以聚合它并转动总计:

select ResponseText, q1, q2, q3
from
(
  select r.ResponseText, d.col
  from WellbeingResponses r
  left join
  (
    select col, value
    from wellbeing
    cross apply
    (
      select 'Q1', Q1 union all
      select 'Q2', Q2 union all
      select 'Q3', Q3
    ) c (col, value)
  ) d
    on r.responseid = d.value
) s
pivot
(
  count(col)
  for col in (Q1, Q2, Q3)
) piv

SQL Fiddle with Demo

获得结果的另一种方法是在wellbeing表上执行多个连接。每个联接都位于question列:

select r.responsetext,
  Q1Total = count(w1.q1),
  Q2Total = count(w2.q2),
  Q3Total = count(w3.q3)
from WellbeingResponses r
left join wellbeing w1
  on r.responseid = w1.q1
left join wellbeing w2
  on r.responseid = w2.q2
left join wellbeing w3
  on r.responseid = w3.q3
group by r.responsetext;

Demo。两个版本都会给出结果:

|     RESPONSETEXT | Q1TOTAL | Q2TOTAL | Q3TOTAL |
|------------------|---------|---------|---------|
|  All of the time |       0 |       0 |       1 |
| Most of the time |       0 |       1 |       0 |
| None of the Time |       1 |       1 |       1 |
|           Rarely |       1 |       0 |       1 |
|        Sometimes |       1 |       1 |       0 |