2012-08-17 40 views
48

phép nói rằng tôi có ba bảng MySQL khác nhau:MySQL trục hàng vào số năng động của cột

Bảng products:

id | name 
1 Product A 
2 Product B 

Bảng partners:

id | name 
1 Partner A 
2 Partner B 

Bảng 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 

Tôi muốn có một bảng với các đối tác trong hàng và sản phẩm dưới dạng cột. Cho đến nay tôi đã có thể để có được một kết quả như thế này:

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 

Sử dụng truy vấn này:

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 

nhưng tôi muốn có thay vì một cái gì đó như:

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 

Vấn đề là rằng tôi không thể biết số lượng sản phẩm tôi sẽ có để số cột cần thay đổi động tùy thuộc vào các hàng trong bảng sản phẩm.

câu trả lời rất tốt này dường như không làm việc với mysql: T-SQL Pivot? Possibility of creating table columns from row values

+0

Liên kết giới thiệu [Row to Column] (https://stackoverflow.com/questions/15745042/efficiently-convert-rows-to-columns-in-sql-server) cho nhiều đề xuất. –

Trả lời

70

Thật không may MySQL không có một chức năng PIVOT mà về cơ bản là những gì bạn đang cố gắng làm. Vì vậy, bạn sẽ cần phải sử dụng một chức năng tổng hợp với một tuyên bố 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 

Xem SQL Fiddle with Demo

Vì bạn không biết các sản phẩm có thể bạn sẽ muốn thực hiện điều này tự động. Điều này có thể được thực hiện bằng cách sử dụng báo cáo chuẩn bị.

Dynamic pivot tables (transform rows to columns)

Mã của bạn sẽ trông như thế này:

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; 

Xem SQL Fiddle with Demo

Có lẽ đáng chú ý là GROUP_CONCAT là theo mặc định giới hạn đến 1024 byte. Bạn có thể làm việc xung quanh điều này bằng cách thiết lập nó cao hơn trong suốt thời gian của thủ tục của bạn, tức là. SET @@group_concat_max_len = 32000;

+2

Nhận xét cuối cùng về "max_len" là một phao cứu sinh! Cảm ơn vì tiền hỗ trợ. – Edward

+1

nếu bạn đang tìm kiếm các truy vấn pivot động hơn, vui lòng kiểm tra điều này: http://www.boynux.com/creating-pivot-reports-in-mysql/ – Boynux

Các vấn đề liên quan