MySQL数据透视表或Excel解决scheme

我有一张桌子:

CREATE TABLE `Issues` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `title` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; 

我有另一张桌子:

 CREATE TABLE `Attachments` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `issue_id` int(11) DEFAULT NULL, `attachment` text, PRIMARY KEY (`id`) ) ENGINE=InnoDB; 

我怎样才能让数据看起来像这样:

 issue_id title attachment1 attachment2 attachment3 -------------------------------------------------------------- 1 T1 a1.png a2.png 2 T2 3 T3 b4.gif xyz.doc ttt.file 

我无法弄清楚的问题是如何将dynamic的附件组合到按问题分组的dynamic列中。 我已经确定一个问题的最大附件数量是12,但是每张票的总数可以是0-12之间的任何地方。 我很难过

我已经试过这个MySQL的数据透视行到dynamic的列数 ,但不能在我的情况下,因为我build立在每个logging总匹配的dynamic列…

任何帮助将不胜感激。 请让我知道这是否没有道理。

尼诺

如果您知道最大数量是12,则可以使用MAXCASE获取每个附件的行号。

 SELECT I.Id issue_id, I.title, MAX(CASE WHEN d.row_number = 1 THEN D.attachment END) attachment1, MAX(CASE WHEN d.row_number = 2 THEN D.attachment END) attachment2, MAX(CASE WHEN d.row_number = 3 THEN D.attachment END) attachment3, MAX(CASE WHEN d.row_number = 4 THEN D.attachment END) attachment4, MAX(CASE WHEN d.row_number = 5 THEN D.attachment END) attachment5, MAX(CASE WHEN d.row_number = 6 THEN D.attachment END) attachment6, MAX(CASE WHEN d.row_number = 7 THEN D.attachment END) attachment7, MAX(CASE WHEN d.row_number = 8 THEN D.attachment END) attachment8, MAX(CASE WHEN d.row_number = 9 THEN D.attachment END) attachment9, MAX(CASE WHEN d.row_number = 10 THEN D.attachment END) attachment10, MAX(CASE WHEN d.row_number = 11 THEN D.attachment END) attachment11, MAX(CASE WHEN d.row_number = 12 THEN D.attachment END) attachment12 FROM Issues I LEFT JOIN ( SELECT a.issue_id, @running:=if(@previous=a.issue_id,@running,0) + 1 as row_number, @previous:=a.issue_id, a.attachment FROM Attachments a JOIN (SELECT @previous := 0) r ORDER BY a.issue_id, a.attachment ) D ON I.ID = D.issue_id GROUP BY I.Id, I.Title 

这里是SQL小提琴 。

我必须做一个编辑,使每个组别的rownumber重置。 应该现在工作。 此外,每@ spencer7593的伟大的评论,我已经稍微更新了查询。

– 编辑 –

为了回应OP对需要dynamic结果的评论,这应该起作用:

SET @sql = NULL;

 SELECT GROUP_CONCAT(DISTINCT CONCAT( 'MAX(IF(d.row_number = ', d.row_number, ',D.attachment,NULL)) AS attachment', d.row_number) ) INTO @sql FROM Issues I LEFT JOIN ( SELECT a.issue_id, @running:=if(@previous=a.issue_id,@running,0) + 1 as row_number, @previous:=a.issue_id, a.attachment FROM Attachments a JOIN (SELECT @previous := 0) r ORDER BY a.issue_id, a.attachment ) D ON I.ID = D.issue_id ; SET @sql = CONCAT('SELECT I.Id issue_id, I.title, ', @sql, ' FROM Issues I LEFT JOIN ( SELECT a.issue_id, @running:=if(@previous=a.issue_id,@running,0) + 1 as row_number, @previous:=a.issue_id, a.attachment FROM Attachments a JOIN (SELECT @previous := 0) r ORDER BY a.issue_id, a.attachment ) D ON I.ID = D.issue_id GROUP BY I.Id, I.Title'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; 

这里是SQL小提琴 。

由SELECT语句返回的一组列是静态定义的。 SELECT语句不能返回“可变”数量的列。

如果你可以定义要返回的列,你可以生成你所显示的结果集,在你的情况下,这意味着定义一行将返回的最大数量的attachment值(列)。

获取结果集的一种方法是在SELECT列表中使用相关的子查询来返回attachment值的第一,第二,第三等事件。

 SELECT i.id , i.title , ( SELECT a1.attachment FROM `Attachments` a1 WHERE a1.issue_id = i.id ORDER BY a1.id LIMIT 0,1 ) AS attachment1 , ( SELECT a2.attachment FROM `Attachments` a2 WHERE a2.issue_id = i.id ORDER BY a2.id LIMIT 1,1 ) AS attachment2 , ( SELECT a3.attachment FROM `Attachments` a3 WHERE a3.issue_id = i.id ORDER BY a3.id LIMIT 2,1 ) AS attachment3 FROM `Issues` i ORDER BY i.id 

要返回您的最大数量的附件,您将需要扩展…

  , ( SELECT a4.attachment FROM `Attachments` a4 WHERE a4.issue_id = i.id ORDER BY a4.id LIMIT 3,1 ) AS attachment4 

ORDER BY的目的是为了使查询的结果集成为确定性的(缺lessORDER BY,MySQL可以按照自己想要的顺序返回行)。

LIMIT子句的用途是指定只返回1行。 LIMIT 0,1指定从第一行(0)开始返回1行。 LIMIT 1,1只返回第二行。


这不是唯一的方法,可能不是最有效的。 它可以合理地工作从外部查询返回的less量行(在你的情况下,从Issues表)。为这个语句生成的“嵌套循环”计划可能是一个大集合资源密集(即慢)。

为了获得最佳性能,您可能需要一个索引…

 ON `Attachments` (issue_id, id) 

或者至less是

 ON `Attachments` (issue_id) 

如果您确实需要返回一个“dynamic”数字,则最好将attachment值作为单独的行返回,并处理从客户端的SQL语句返回的结果集。