我有3张桌子,我需要从中获取一个数据透视表。
+------------+----------+ | idQuestion | question | +------------+----------+ | 1 | Q1 | +------------+----------+ | 2 | Q2 | +------------+----------+
+------------+------------+----------+-------+ | idAnswer | idQuestion | answer | value | +------------+------------+----------+-------+ | 1 | 1 | A1 | 100 | +------------+------------+----------+-------+ | 2 | 1 | A2 | 101 | +------------+------------+----------+-------+ | 3 | 2 | B1 | 200 | +------------+------------+----------+-------+
+------------+------------+----------+-------+ | idResult | idAnswer | idUser | .... | +------------+------------+----------+-------+ | 1 | 1 | u1 | ... | +------------+------------+----------+-------+ | 2 | 1 | u2 | ... | +------------+------------+----------+-------+ | 3 | 3 | u3 | ... | +------------+------------+----------+-------+
我需要从结果中获取数据透视表。我需要它喜欢这样的东西:
+---------+--------------+--------------+--------------+
| idUser | Q1 | Q2 | Qn |
+---------+--------------+--------------+--------------+
| u1 | answer.value | answer.value | answer.value |
+---------+--------------+--------------+--------------+
| u2 | answer.value | answer.value | answer.value |
+---------+--------------+--------------+--------------+
| u2 | answer.value | answer.value | answer.value |
+---------+--------------+--------------+--------------+
我已经阅读了很多问题,看到了许多决议,但没有任何问题符合我的问题。
答案 0 :(得分:0)
如问题所示,结果集无法使用单个SELECT语句获得。
获得此类结果的一种方法是考虑获得这样的结果:
+---------+----+-------------+-------------+-------------+
| idUser | q | a.value | a.value | a.value |
+---------+----+-------------+-------------+-------------+
| u1 | Q1 | a.value=101 | a.value=101 | a.value=101 |
| u1 | Q2 | a.value=200 | a.value=200 | a.value=200 |
| u1 | Qn | a.value=NNN | a.value=NNN | a.value=NNN |
即每个用户和问题的一行,以及答案。考虑在每个Ans.x
列中重复的SAME答案。
“技巧”是用于返回每个a.value列的表达式,使用条件测试来查看q
是否与我们想要返回的特定question
相匹配特定栏目......
SELECT r.idUser
, q.q
, IF(q.q='Q1',a.value,NULL) AS AnsQ1
, IF(q.q='Q2',a.value,NULL) AS AnsQ2
, IF(q.q='Qn',a.value,NULL) AS AnsQn
, ...
FROM ...
所以我们会得到这样的结果:
+---------+----+-------------+-------------+-------------+
| idUser | q | AnsQ1 | AnsQ2 | AnsQn |
+---------+----+-------------+-------------+-------------+
| u1 | Q1 | a.value=101 | NULL | NULL |
| u1 | Q2 | NULL | a.value=200 | NULL |
| u1 | Qn | NULL | NULL | a.value=NNN |
使用该结果,我们可以添加GROUP BY idUser
,并使用聚合函数(MIN()
或MAX()
)来选择非NULL的答案value
SELECT r.idUser
, MAX(IF(t.q='Q1',a.value,NULL)) AS AnsQ1
, MAX(IF(t.q='Q2',a.value,NULL)) AS AnsQ2
, MAX(IF(t.q='Qn',a.value,NULL)) AS AnsQn
, ...
FROM ...
GROUP BY r.idUser
获得这样的结果:
+---------+-------------+-------------+-------------+
| idUser | AnsQ1 | AnsQ2 | AnsQn |
+---------+-------------+-------------+-------------+
| u1 | a.value=101 | a.value=200 | a.value=NNN |
但问题是:不可能动态更改返回的列数,或动态更改SQL语句从返回的列的数据类型或名称/ em> SQL语句。
列的数量,数据类型和列的名称......在将SELECT语句提交到数据库时,这些都必须是FIXED。
因此,在底线,结果集不能从单 SELECT语句中的表中返回,不能使用表中的值作为列名,或者改变列数从声明中返回。
然而,事先可以使用单独的 SQL语句来从表中获取信息,因此我们可以动态构建获取结果集所需的查询。
注意:上面说明的MAX(IF(,val,NULL)) ... GROUP BY ...
模式只是一种方法。可能,您也遇到了“SELECT列表中的相关子查询”模式的答案。同样的方法适用:运行查询,获取构建查询所需的元数据,然后为第二个查询构建SQL文本(返回实际需要的结果)。