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,则可以使用MAX
和CASE
获取每个附件的行号。
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语句返回的结果集。