我无法使用以下表格在MySQL中创建数据透视表:
Teams ------------- id | name 1 | teamA Processes ------------- id | name 1 | processA 2 | processB ProcessDetails --------------- id | processId | keyName 1 | 1 | shape 2 | 1 | vegetable 3 | 1 | fruit 4 | 2 | animal TeamProcesses ----------------- id | teamId | processId 5 | 1 | 1 6 | 1 | 2 TeamProcessDetails -------------------- id | teamProcessId | proccessDetailsId | value 1 | 5 | 1 | circle 2 | 5 | 2 | carrot 3 | 5 | 3 | apple 4 | 6 | 4 | dog
我正在尝试生成的数据透视表是这个:
Pivot Table ------------ teamId | processId | shape | vegetable | fruit | animal 1 | 1 | circle | carrot | apple | NULL 1 | 2 | NULL | NULL | NULL | dog
应当指出,键的数量是动态的,因此我认为我需要使用准备好的语句方法。而且,进程没有相同的键,因此它们应该仅具有属于该进程的键的值。
谢谢!
当您尝试使用动态或未知值时,我总是建议您先使用静态或硬编码版本的查询,然后再将其转换为动态SQL。
MySQL没有PIVOT函数,因此您将需要使用带有CASE表达式的聚合函数来获取结果。该代码的静态版本将类似于以下内容:
select t.id teamid, t.name teamname, p.id processid, p.name processname, max(case when pd.keyname = 'shape' then tpd.value end) shape, max(case when pd.keyname = 'vegetable' then tpd.value end) vegetable, max(case when pd.keyname = 'fruit' then tpd.value end) fruit, max(case when pd.keyname = 'animal' then tpd.value end) animal from teams t inner join teamprocesses tp on t.id = tp.teamid inner join TeamProcessDetails tpd on tp.id = tpd.teamProcessId inner join processes p on tp.processid = p.id inner join processdetails pd on p.id = pd.processid and tpd.processDetailsid = pd.id group by t.id, t.name, p.id, p.name;
请参阅带有演示的SQL Fiddle。
现在,如果keynames要转换为列的数量未知,则需要使用准备好的语句来生成动态SQL。该代码将类似于:
keynames
SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT CONCAT( 'max(case when pd.keyname = ''', keyname, ''' then tpd.value end) AS ', replace(keyname, ' ', '') ) ) INTO @sql from ProcessDetails; SET @sql = CONCAT('SELECT t.id teamid, t.name teamname, p.id processid, p.name processname, ', @sql, ' from teams t inner join teamprocesses tp on t.id = tp.teamid inner join TeamProcessDetails tpd on tp.id = tpd.teamProcessId inner join processes p on tp.processid = p.id inner join processdetails pd on p.id = pd.processid and tpd.processDetailsid = pd.id group by t.id, t.name, p.id, p.name;'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
请记住GROUP_CONCAT,创建列字符串的函数的默认最大长度为1024,因此,如果此字符串中包含很多字符,则可能必须更改的会话值group_concat_max_len。
GROUP_CONCAT
group_concat_max_len
该查询将给出结果:
| TEAMID | TEAMNAME | PROCESSID | PROCESSNAME | SHAPE | VEGETABLE | FRUIT | ANIMAL | | 1 | teamA | 1 | processA | circle | carrot | apple | (null) | | 1 | teamA | 2 | processB | (null) | (null) | (null) | dog |