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
行( EMAIL
, PRINT 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()
函数中,并将其评估为布尔0
或1
,因此您可以根据条件进行计数,而无需使用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_CONCAT
和CONCAT
。 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列),行,表格和表格关系中的值(如果有的话)
这个工具的主页是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 ;