2012-12-31 87 views
0

好吧,我仍然是一個初學者在SQL中,並不能找出這一個。 我有四個表格:公司,人員,細節,person_details。mysql數據透視表或東西

companies: 
id, compname 
(1, ACME), 
(2, ACME Group), ... 

persons: 
id, name, lastname, company id 
(1, donald, duck, 1), 
(2, lucky, luke, 1), 
(3, mickey, mouse, 2) 

details: 
id, description 
(1, 'weight'), 
(2, 'height'), 
(3, 'haircolor'), ... 

person_details: 
id, persons id, details id, value 
(1, 1, 1, 70), 
(2, 1, 3, 'red'), 
(3, 2, 1, 90), 
(4, 3, 2, 180) 

正如您所看到的,並非所有人都具有所有細節,可用詳細信息列表是可變的。

現在,對於給定的人員ID和詳細ID文檔,我希望獲取包含公司名稱和ID,人員名稱和姓氏,所提供數組中的每個詳細信息的詳細名稱和值的行。 比方說,人(1,2),細節(1,3)應導致:

companies.id, companies.name, name, lastname, details.description, person_details.value,...  
    1, ACME, donald, duck, 'weight', 70, 'haircolor', 'red' 
    2, ACEM, lucky, luke, 'weight', 90, 'haircolor', null 

幫助,請...根據您的描述

+0

更新你的上面表的正確列名的輸出數據。並且還更新你嘗試過什麼? –

+0

我更新了輸出數據。嘗試了各種各樣的東西,但作爲初學者,不知道它是否有意義... – user1768401

回答

1

好像要的數據,但不幸的是,MySQL沒有關鍵點函數,因此您需要使用具有CASE語句的聚合函數來複制它。

如果你提前知道了描述值的時候,你可以硬編碼查詢到以下幾點:

select c.id, 
    c.compname, 
    p.name, 
    p.lastname, 
    max(case when d.description = 'weight' then pd.value end) weight, 
    max(case when d.description = 'haircolor' then pd.value end) haircolor, 
    max(case when d.description = 'height' then pd.value end) height 
from companies c 
left join persons p 
    on c.id = p.`company id` 
left join person_details pd 
    on p.id = pd.`persons id` 
left join details d 
    on pd.`details id` = d.id 
-- where p.id in (1, 2) 
group by c.id, c.compname, p.name, p.lastname 

SQL Fiddle with Demo

如果你有一個未知的數值,那麼你可以使用一個prepared statement to generate this dynamically此類似:

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'MAX(CASE WHEN d.description = ''', 
     description, 
     ''' then pd.value end) AS ', 
     description 
    ) 
) INTO @sql 
FROM details; 

SET @sql = CONCAT('SELECT c.id, 
         c.compname, 
         p.name, 
         p.lastname, ', @sql, ' 
        from companies c 
        left join persons p 
        on c.id = p.`company id` 
        left join person_details pd 
        on p.id = pd.`persons id` 
        left join details d 
        on pd.`details id` = d.id 
        -- where p.id in (1, 2) 
        group by c.id, c.compname, p.name, p.lastname'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

SQL Fiddle with Demo

兩個版本產生的結果是:

| ID | COMPNAME | NAME | LASTNAME | WEIGHT | HEIGHT | HAIRCOLOR | 
--------------------------------------------------------------------- 
| 1 |  ACME | donald |  duck |  70 | (null) |  red | 
| 1 |  ACME | lucky |  luke |  90 | (null) | (null) | 
| 2 | ACME Group | mickey | mouse | (null) | 180 | (null) | 
+0

謝謝,這正是我需要的。你只會忘記在'從細節'之後添加'where id in(1,3)'。爲了充分理解發生了什麼,撓了撓頭,但我已經明白了。再次感謝。 – user1768401

+0

@ user1768401我剛剛評論過,所以你可以看到整個解決方案。 :) – Taryn