2012-06-12 90 views
3

我有以下數據庫設計的麻煩(爲例子簡化)。它允許人們創建自定義表單,與Google spreadheat表單非常相似。表單生成腳本已完成,包括將答案保存到數據庫。我無法顯示用戶輸入。有很多表的複雜查詢,這可能在一個查詢中?

形式(各形式是在該表中的行)

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  

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    [email protected] 
3   1    3    Test message 
4   1    4    This is a test. Regards, Barack. 
5   2    1    Thomas something 
6   2    2    [email protected] 
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... [email protected] Test... This is a t... 
2 114869... Thomas... [email protected] 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! 

是否如果與任何人怎麼可以做到這一點?

非常感謝任何願意花時間照亮這個問題的人!

+0

你想要兩個選擇,一個爲每種類型的? –

回答

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中使用樞軸例子。也有在計算器上其他的答案,應該是能夠幫助動態寫這個:

mysql query to dynamically convert row data to columns

MySQL pivot table with dynamic headers based on single column data

+0

這個作品,你是我的英雄! – dirk

1

不錯的標準化模式!

在純SQL中執行此操作非常困難,因爲您需要創建具有來自您的questions.question_name中的行的列名別名的查詢。

如果你是用純SQL做的話,你會編寫SQL語句,以某種方式爲每個不同的form_id值寫入SQL語句。這導致您的SQL代碼中存在一些不可維護的猴子業務。它會完全吹走你所做的工作,以便能夠輕鬆處理多種表單,從而節省您的長期成本。

這對於PHP,PERL,Java或其他一些操作字符串列表的作業很容易。

PostgreSQL和Oracle允許您使用Java和/或PERL等語言編寫存儲過程。如果您的必須將此代碼駐留在您的數據庫管理系統中,那麼這可能就是要走的路。