MySQL数据透视表

如果我有一个MySQL表,看起来像这样:

 company_name操作页面数
 -------------------------------
公司A PRINT 3
公司A PRINT 2
公司A PRINT 3
公司B电子邮件   
公司B PRINT 2
公司B PRINT 2
公司B打印1
公司A PRINT 3

是否有可能运行MySQL查询来获得这样的输出:

 company_name电子邮件打印1页打印2页打印3页
 -------------------------------------------------- -----------
 CompanyA 0 0 1 3
公司B 1 1 2 0

这个想法是, pagecount可以改变,所以输出列的数量应该反映,每个action / pagecount对一列,然后每个company_name命中数。 我不确定这是否被称为数据透视表,但有人build议?

这基本上一个数据透视表。

一个很好的教程如何实现这个可以在这里find: http : //www.artfulsoftware.com/infotree/qrytip.php?id=78

我build议阅读这篇文章,并根据您的需求调整这个解决scheme。

更新

上面的链接目前不可用后,我觉得有义务提供一些额外的信息,为您在这里searchMySQL数据透视答案。 它真的有大量的信息,我不会把所有的东西都放在这里(甚至更多,因为我不想复制他们的知识),但是我会给出一些关于如何处理透视的build议从一开始就提出问题的peku的例子一般表sql方式。

也许链接很快就会回来,我会留意的。

电子表格的方式…

许多人只是使用像MSExcel,OpenOffice或其他电子表格工具为此目的的工具。 这是一个有效的解决scheme,只需复制那里的数据,并使用GUI提供的工具来解决这个问题。

但是,这不是问题,它甚至可能导致一些不利之处,比如如何将数据导入电子表格,有问题的缩放等等。

SQL的方式…

鉴于他的桌子看起来像这样:

 CREATE TABLE `test_pivot` ( `pid` bigint(20) NOT NULL AUTO_INCREMENT, `company_name` varchar(32) DEFAULT NULL, `action` varchar(16) DEFAULT NULL, `pagecount` bigint(20) DEFAULT NULL, PRIMARY KEY (`pid`) ) ENGINE=MyISAM; 

现在看看他/她想要的表格:

 company_name EMAIL PRINT 1 pages PRINT 2 pages PRINT 3 pages ------------------------------------------------------------- CompanyA 0 0 1 3 CompanyB 1 1 2 0 

行( EMAILPRINT x pages )与条件类似。 主要分组是由company_name

为了build立这个条件,而不是使用CASE -statement喊话。 为了按某种方式进行分组,请使用… GROUP BY

提供这个支点的基本SQL可以看起来像这样:

 SELECT P.`company_name`, COUNT( CASE WHEN P.`action`='EMAIL' THEN 1 ELSE NULL END ) AS 'EMAIL', COUNT( CASE WHEN P.`action`='PRINT' AND P.`pagecount` = '1' THEN P.`pagecount` ELSE NULL END ) AS 'PRINT 1 pages', COUNT( CASE WHEN P.`action`='PRINT' AND P.`pagecount` = '2' THEN P.`pagecount` ELSE NULL END ) AS 'PRINT 2 pages', COUNT( CASE WHEN P.`action`='PRINT' AND P.`pagecount` = '3' THEN P.`pagecount` ELSE NULL END ) AS 'PRINT 3 pages' FROM test_pivot P GROUP BY P.`company_name`; 

这应该非常快速地提供期望的结果。 这种方法的主要缺点是,数据透视表中需要的行越多,需要在SQL语句中定义的条件就越多。

这也可以处理,所以人们倾向于使用准备好的陈述,例程,计数器等等。

关于此主题的一些其他链接:

我的解决scheme是在没有任何支点的T-SQL中:

 SELECT CompanyName, SUM(CASE WHEN (action='EMAIL') THEN 1 ELSE 0 END) AS Email, SUM(CASE WHEN (action='PRINT' AND pagecount=1) THEN 1 ELSE 0 END) AS Print1Pages, SUM(CASE WHEN (action='PRINT' AND pagecount=2) THEN 1 ELSE 0 END) AS Print2Pages, SUM(CASE WHEN (action='PRINT' AND pagecount=3) THEN 1 ELSE 0 END) AS Print3Pages FROM Company GROUP BY CompanyName 

对于MySQL,您可以直接将条件放在SUM()函数中,并将其评估为布尔01 ,因此您可以根据条件进行计数,而无需使用IF/CASE语句

 SELECT company_name, SUM(action = 'EMAIL')AS Email, SUM(action = 'PRINT' AND pagecount = 1)AS Print1Pages, SUM(action = 'PRINT' AND pagecount = 2)AS Print2Pages, SUM(action = 'PRINT' AND pagecount = 3)AS Print3Pages FROM t GROUP BY company_name 

DEMO

对于dynamic数据透视表,使用GROUP_CONCATCONCAT 。 GROUP_CONCAT函数将来自组的string连接成具有不同选项的一个string。

 SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT CONCAT( 'SUM(CASE WHEN action = "', action,'" AND ', (CASE WHEN pagecount IS NOT NULL THEN CONCAT("pagecount = ",pagecount) ELSE pagecount IS NULL END), ' THEN 1 ELSE 0 end) AS ', action, IFNULL(pagecount,'') ) ) INTO @sql FROM t; SET @sql = CONCAT('SELECT company_name, ', @sql, ' FROM t GROUP BY company_name'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; 

在这里演示

使用布尔逻辑的 stardard-SQL版本:

 SELECT company_name , COUNT(action = 'EMAIL' OR NULL) AS "Email" , COUNT(action = 'PRINT' AND pagecount = 1 OR NULL) AS "Print 1 pages" , COUNT(action = 'PRINT' AND pagecount = 2 OR NULL) AS "Print 2 pages" , COUNT(action = 'PRINT' AND pagecount = 3 OR NULL) AS "Print 3 pages" FROM tbl GROUP BY company_name; 

SQL小提琴。

怎么样?

TRUE OR NULL TRUE
FALSE OR NULL产生NULL
NULL OR NULL产生NULL
COUNT只计算非空值。 瞧。

有一个名为MySQL Pivot表生成器的工具,它可以帮助您创build基于Web的数据透视表,您可以稍后导出为Excel(如果您喜欢)。 它可以工作,如果你的数据是在一个表或几个表中。

您只需指定列的数据源(它支持dynamic列),行,表格和表格关系中的值(如果有的话) MySQL数据透视表

这个工具的主页是http://mysqlpivottable.net

正确答案是:

 select table_record_id, group_concat(if(value_name='note', value_text, NULL)) as note ,group_concat(if(value_name='hire_date', value_text, NULL)) as hire_date ,group_concat(if(value_name='termination_date', value_text, NULL)) as termination_date ,group_concat(if(value_name='department', value_text, NULL)) as department ,group_concat(if(value_name='reporting_to', value_text, NULL)) as reporting_to ,group_concat(if(value_name='shift_start_time', value_text, NULL)) as shift_start_time ,group_concat(if(value_name='shift_end_time', value_text, NULL)) as shift_end_time from other_value where table_name = 'employee' and is_active = 'y' and is_deleted = 'n' GROUP BY table_record_id 
 select t3.name, sum(t3.prod_A) as Prod_A, sum(t3.prod_B) as Prod_B, sum(t3.prod_C) as Prod_C, sum(t3.prod_D) as Prod_D, sum(t3.prod_E) as Prod_E from (select t2.name as name, case when t2.prodid = 1 then t2.counts else 0 end prod_A, case when t2.prodid = 2 then t2.counts else 0 end prod_B, case when t2.prodid = 3 then t2.counts else 0 end prod_C, case when t2.prodid = 4 then t2.counts else 0 end prod_D, case when t2.prodid = "5" then t2.counts else 0 end prod_E from (SELECT partners.name as name, sales.products_id as prodid, count(products.name) as counts FROM test.sales left outer join test.partners on sales.partners_id = partners.id left outer join test.products on sales.products_id = products.id where sales.partners_id = partners.id and sales.products_id = products.id group by partners.name, prodid) t2) t3 group by t3.name ;