3

我在以下数据库设计方面遇到了麻烦(为示例进行了简化)。它允许人们创建自定义表单,与谷歌电子表格非常相似。表单生成脚本完成,包括将答案保存到数据库。我无法显示用户输入。

表格表格(每个表格在此表格中是一行)

form_id | form_name
1         Contact Form
2         BBQ sign up Form

表格问题(表格中的问题)

question_id | form_id | question_name      | sorting_order
1             1         Full Name            1
2             1         E-mail address       2
3             1         Subject              3
4             1         Message              4
5             2         Your name            1
6             2         Are you vegetarian?  2
7             2         Beer or wine?        3    

table completed_forms(将答案组合在一起)

complete_id | form_id | timestamp
1            1          1339496914
2            1          1148691493
3            2          1256235334

表格答案(用户对特定问题的回答)

answer_id | complete_id | question_id | answer
1           1             1             Barack Obama
2           1             2             president@whitehouse.gov
3           1             3             Test message
4           1             4             This is a test. Regards, Barack.
5           2             1             Thomas something
6           2             2             thomas@email.com
7           2             3             Another message
8           2             4             Hey, it's Thomas. This is my message.
9           3             5             Dirk
10          3             6             No, I love meat
11          3             7             Red wine!

我要显示的是用户输入的概述,这非常复杂,因为每个表单的名称和列数不同。例如,我想显示来自联系人表单 (form_id: 1) 的用户输入,如下所示:

id | timestamp | Full Name | E-mail Address | Subject | Message
1    133949...   Barack...   president@w...   Test...   This is a t...
2    114869...   Thomas...   thomas@emai...   Anot...   Hey, it's T...

并从 form_id 2 如下:

id | timestamp | Your name | Are you vegetarian? | Beer or Wine?
3    125623...   Dirk        No, I love meat       Red wine!

有谁如果以及如何实现这一目标?

非常感谢任何愿意花时间来解决这个问题的人!

4

2 回答 2

3

基本上,您正在尝试编写 PIVOT,但 MySQL 本身没有 PIVOT 函数,因此您必须编写稍微不同的查询。对于此查询的静态版本,您将在问题的值中进行编码,您可以使用以下内容:

表格 1(参见SQL Fiddle with Demo):

select cf.complete_id
  , cf.ts
  , Min(CASE WHEN q.question_name = 'Full Name' THEN a.answer END) as 'Full Name'
  , Min(CASE WHEN q.question_name = 'Email Address' THEN a.answer END) as 'Email Address'
  , Min(CASE WHEN q.question_name = 'Subject' THEN a.answer END) as 'Subject'
  , Min(CASE WHEN q.question_name = 'Message' THEN a.answer END) as 'Message'
from completed_forms cf
inner join questions q
  on cf.form_id = q.form_id
inner join answers a
  on cf.complete_id = a.complete_id
  and q.question_id = a.question_id
where cf.form_id = 1
group by cf.complete_id

表格 2(参见SQL Fiddle with Demo):

select cf.complete_id
  , cf.ts
  , Min(CASE WHEN q.question_name = 'Your Name' THEN a.answer END) as 'Your Name'
  , Min(CASE WHEN q.question_name = 'Are you vegetarian?' THEN a.answer END) as 'Are you vegetarian?'
  , Min(CASE WHEN q.question_name = 'Beer or Wine' THEN a.answer END) as 'Beer or Wine'
from completed_forms cf
inner join questions q
  on cf.form_id = q.form_id
inner join answers a
  on cf.complete_id = a.complete_id
  and q.question_id = a.question_id
where cf.form_id = 2
group by cf.complete_id

现在,由于每个表单的问题都会发生变化,那么您应该考虑使 Pivot 自动化。我建议查看位于此处的文章:

http://www.artfulsoftware.com/infotree/queries.php#523

它包含如何在 MySql 中使用枢轴的示例。StackOverflow 上还有其他答案应该能够帮助动态编写这个:

mysql查询将行数据动态转换为列

具有基于单列数据的动态标题的 MySQL 数据透视表

于 2012-06-12T11:44:09.023 回答
1

很好的标准化架构!

在纯 SQL 中执行此操作非常困难,因为您需要创建具有列名别名的查询,这些别名来自您的 questions.question_name 中的行。

如果您在纯 SQL 中执行此操作,那么您将编写 SQL 语句,该语句会以某种方式为 form_id 的每个不同值编写 SQL 语句。这会导致您的 SQL 代码中出现一些无法维护的猴子业务。就您的长期成本而言,这将彻底消除您为能够轻松处理多种表格所做的工作。

这在 PHP、PERL、Java 或其他在处理字符串列表方面做得不错的语言中要容易得多。

PostgreSQL 和 Oracle 允许您使用 Java 和/或 PERL 等语言编写存储过程。如果您必须将此代码驻留在您的 DBMS 中,那么这可能就是您要走的路。

于 2012-06-12T11:18:35.643 回答