2012-12-31 47 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