mysql数据透视表或其他东西

时间:2012-12-31 10:54:14

标签: mysql sql pivot pivot-table

好的,我还是sql的初学者,还不能解决这个问题。 我有四张桌子:公司,人员,细节,person_details。

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

请帮助......

1 个答案:

答案 0 :(得分:1)

根据您的描述,您似乎想要转移数据,但遗憾的是MySQL没有 pivot 功能,因此您需要使用聚合函数复制它使用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) |
相关问题