2012-08-17 77 views
48

的动态数量可以说我有三个不同的MySQL表:MySQL的支点行成列

products

id | name 
1 Product A 
2 Product B 

partners

id | name 
1 Partner A 
2 Partner B 

sales

partners_id | products_id 
      1    2 
      2    5 
      1    5 
      1    3 
      1    4 
      1    5 
      2    2 
      2    4 
      2    3 
      1    1 

我想获得一个表格作为列的行和产品的合作伙伴。到目前为止,我能得到这样的输出:

name  | name  | COUNT(*) 
Partner A Product A   1 
Partner A Product B   1 
Partner A Product C   1 
Partner A Product D   1 
Partner A Product E   2 
Partner B Product B   1 
Partner B Product C   1 
Partner B Product D   1 
Partner B Product E   1 

使用此查询:

SELECT partners.name, products.name, COUNT(*) 
FROM sales 
JOIN products ON sales.products_id = products.id 
JOIN partners ON sales.partners_id = partners.id 
GROUP BY sales.partners_id, sales.products_id 
LIMIT 0 , 30 

,但我想有而不是这样的:

partner_name | Product A | Product B | Product C | Product D | Product E 
Partner A    1   1   1   1   2 
Partner B    0   1   1   1   1 

的问题是我不能说出我有多少产品,所以列号需要根据产品表中的行动态更改。

这很好的答案似乎不使用MySQL:T-SQL Pivot? Possibility of creating table columns from row values

+0

请参考[行到列]链接(https://stackoverflow.com/questions/15745042/efficiently-convert-rows-to-columns-in-sql-server)获取多个建议。 – 2018-02-01 06:00:53

回答

70

不幸的是,MySQL没有一个PIVOT功能基本上是你正在尝试做的。所以,你需要使用一个聚合函数与CASE声明:

select pt.partner_name, 
    count(case when pd.product_name = 'Product A' THEN 1 END) ProductA, 
    count(case when pd.product_name = 'Product B' THEN 1 END) ProductB, 
    count(case when pd.product_name = 'Product C' THEN 1 END) ProductC, 
    count(case when pd.product_name = 'Product D' THEN 1 END) ProductD, 
    count(case when pd.product_name = 'Product E' THEN 1 END) ProductE 
from partners pt 
left join sales s 
    on pt.part_id = s.partner_id 
left join products pd 
    on s.product_id = pd.prod_id 
group by pt.partner_name 

SQL Fiddle with Demo

既然你不知道,你可能会想动态执行此产品。这可以使用预准备语句来完成。

Dynamic pivot tables (transform rows to columns)

您的代码应该是这样的:

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'count(case when Product_Name = ''', 
     Product_Name, 
     ''' then 1 end) AS ', 
     replace(Product_Name, ' ', '') 
    ) 
) INTO @sql 
from products; 

SET @sql = CONCAT('SELECT pt.partner_name, ', @sql, ' from partners pt 
left join sales s 
    on pt.part_id = s.partner_id 
left join products pd 
    on s.product_id = pd.prod_id 
group by pt.partner_name'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

SQL Fiddle with Demo

这也许值得一提的是GROUP_CONCAT默认限制为1024个字节。你可以通过在你的程序期间将它设置得更高来解决这个问题。 SET @@group_concat_max_len = 32000;

+2

关于“max_len”最后的评论是一个救星!谢谢你的提示。 – Edward 2013-11-13 17:49:55

+1

如果您正在寻找更多的动态数据透视查询,请查看:http://www.boynux.com/creating-pivot-reports-in-mysql/ – Boynux 2013-11-29 03:14:04