2015-01-12 96 views
0

我想構建一個查詢來從表單生成器中提取數據,我可以只在其他字段值等於特定值時在字段值上加入數據。我的查詢返回沒有行。MySQL加入特定結果

users 
------------------ 
|id | name  | 
------------------ 
|40 | John  | 
|45 | Michael | 
|47 | Bob  | 
------------------  

data_table 
---------------------------------------------------- 
|id | submission | field_type | field_value  | 
---------------------------------------------------- 
|1 | 12345  | user  | 40    | 
|2 | 12345  | score  | 5     | 
|3 | 12345  | completed | 1     | 
|4 | 23456  | user  | 45    | 
|5 | 23456  | score  | 3     | 
|6 | 23456  | completed | 0     | 
|7 | 45678  | user  | 47    | 
|8 | 45678  | score  | 2     | 
|9 | 45678  | completed | 1     | 
---------------------------------------------------- 

Desired result 

--------------- 
|Name | Score | 
--------------- 
|John | 5  | 
|Bob | 2  | 
--------------- 

Select 
    u.name, 
    dt2.field_value as score 
from 
    users u 
left join 
    data_table dt on u.id=dt.field_value and dt.field_type='user' 
left join 
    data_table dt2 on dt.submission=dt2.submission and dt2.field_type='score' 
where 
    (dt.field_type='completed' and dt.field_value=1) 

http://sqlfiddle.com/#!2/d6e72f/3

+1

你在問不可能的條件。你加入'dt.field_type ='user'',所以'dt'中的**只有**記錄可以用於'where'過濾是'user'記錄。將不會有任何'完成'記錄... –

回答

1

你可以做這樣的事情(如果你真的不能改變你的數據結構,這看起來......怪)。

你必須在data_table子查詢,有兩個自連接在該表(根據您的需要與條件,3個不同的行)

select u.name, s.score 
from users u 
join (
     select dt.field_value as user_id, dt1.field_value as score 
     from data_table dt 
     join data_table dt1 on dt1.submission = dt.submission 
     join data_table dt2 on dt2.submission = dt1.submission 
     where dt.field_type='user' and 
      dt1.field_type = 'score' and 
      dt2.field_type='completed' and 
      dt2.field_value = 1 
    ) s 
    on s.user_id = u.id 

看到SqlFiddle

+0

謝謝拉斐爾我會檢查這一點 - 我不能改變結構,它看起來很奇怪,但它是一個系統,允許用戶從頭開始構建表單並存儲在MySQL中的內容,然後訪問數據的報告等等。在這兩個表中有更多的字段,但它們並不真正相關,所以我把它們排除在外 – bhttoan

1

工作撥弄http://sqlfiddle.com/#!2/d6e72f/19/0

當用戶動態添加其他屬性到現有結構時,我已經看到了很多。您必須首先取消其他數據,然後將其視爲普通表格。由於mysql不支持unpivot,我使用了正常的解決方法。

Select u.name, score 
from users u 
INNER JOIN (
Select submission, 
    max(case when field_Type='user' then field_value end) as user, 
    max(case when field_Type='score' then field_value end) as score, 
    max(case when field_Type='completed' then field_value end) as completed    
FROM data_table 
group by submission) dt 
    on dt.user = u.id 
and dt.completed = 1 

這假設對於給定的提交,不能有多個field_Type值組合。如果有,這隻會返回最大值。

基本上,這樣做是將數據轉移到一個表格結構中,然後我們可以將它們連接回去。

我們做max或min的原因是爲了讓我們得到一行而不是給定提交的多行。再次,這只是簡單地將數據取消轉換並將行組合成一個。但是基於一個假設,即field_type和field_value在提交中不會重複。

1

讓我們來看看你實際上是在做什麼,所以我們可以看到什麼錯誤:

Select 
    u.name, 
    dt2.field_value as score 
from 
    users u 

獲取用戶的列表

left join 
    data_table dt on u.id=dt.field_value and dt.field_type='user' 

從data_table類型的加入只是行「用戶'

left join 
    data_table dt2 on dt.submission=dt2.submission and dt2.field_type='score' 

僅加入類型爲'score'的data_table中的行。 現在你的結果集看起來像:

用戶,DT(數據錶行類型「用戶」),DT2(數據錶行類型「SCORE」)

where 
    (dt.field_type='completed' and dt.field_value=1) 

篩選的結果,包括只有dt.field_type(以前被過濾爲僅包含類型「用戶」)的用戶的類型爲「完成」。

基本上你的連接過濾掉'data_table'中的所有'完整'行,所以你的where語句找不到任何匹配。這只是解釋發生了什麼。解決你的問題。

看看你的模式,你有幾個選擇。雖然我是不是設計的粉絲,這裏是我會怎麼寫你的查詢了:

SELECT U.name, SCORE_DT.field_value AS score 
FROM user U 
JOIN data_table DT ON DT.field_value=U.id AND DT.field_type="USER" 
JOIN data_table SCORE_DT ON SCORE_DT.submission=DT.submission AND SCORE_DT.field_type="SCORE" 
JOIN data_table COMPLETED_DT.submission=DT.submission AND COMPLETED_DT.field_type="COMPLETED" AND COMPLETED_DT.field_value=1 

實際上,它會使你的生活更容易地更改表的設計,因爲這種數據結構需要你構建查詢,對您感興趣的每一列執行數據透視操作。對於像這樣的小數據集是可行的,但隨着表單中列的數量增加,它將變得非常繁瑣。

+0

謝謝你解釋我出錯的地方 – bhttoan

1

的作品是另一種變化......

select x.name 
    , d.field_value 
from data_table d 
join (select u.name 
      , d2.submission 
     from users  u 
     join data_table d2 
        on d2.field_value = u.id 
        and d2.field_type = 'user' 
     join data_table d3 
        on d2.submission = d3.submission 
        and d3.field_type = 'completed' 
        and d3.field_value = '1' 
     ) x 
      on x.submission = d.submission 
      and d.field_type = 'score' 

看到SqlFiddle

爲了您的一組數據,你會發現這樣或xQbert的回答表現不同。 我會給他們一個嘗試。根據您的數據,嘗試獲取最內層查詢以返回可能的最小數據集。例如,如果您知道只有data_table記錄的一小部分將具有'completed'='1',則第三個嵌套select可能不會不合理,如果它導致MySql使用較小的結果。