2012-08-17 15 views
48

Lets sagen, ich habe drei verschiedene MySQL-Tabellen:MySQL Pivotzeile in dynamische Anzahl der Spalten

Tabelle products:

id | name 
1 Product A 
2 Product B 

Tabelle partners:

id | name 
1 Partner A 
2 Partner B 

Tabelle 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 

Ich möchte eine Tabelle mit den Partnern in den Reihen und Produkte als Spalten erhalten. Bisher konnte ich eine Ausgabe wie folgt erhalten:

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 

diese Abfrage verwenden:

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 

aber ich möchte wie anstatt etwas haben:

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 

Das Problem ist, dass ich nicht sagen kann, wie viele Produkte ich haben werde, so dass die Spaltennummer dynamisch geändert werden muss, abhängig von den Zeilen in der Produkttabelle.

Diese sehr gute Antwort scheint nicht mit MySQL zu arbeiten: T-SQL Pivot? Possibility of creating table columns from row values

+0

Verweis für mehrere Vorschläge verweisen Sie auf [Zeile zu Spalte] (https://stackoverflow.com/questions/15745042/efficiently-convert-rows-to-columns-in-sql-server). –

Antwort

70

Leider MySQL hat keine PIVOT Funktion, die im Grunde ist das, was Sie zu tun versuchen. So müssen Sie eine Aggregatfunktion mit einer CASE Anweisung:

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 

Siehe SQL Fiddle with Demo

Da Sie nicht über die Produkte wissen Sie wahrscheinlich diese dynamisch ausführen wollen. Dies kann mit vorbereiteten Anweisungen geschehen.

Dynamic pivot tables (transform rows to columns)

Ihr Code würde wie folgt aussehen:

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; 

Siehe SQL Fiddle with Demo

Es ist wahrscheinlich erwähnenswert, dass GROUP_CONCAT standardmäßig auf 1024 Byte begrenzt ist. Sie können dies umgehen, indem Sie es für die Dauer Ihres Verfahrens höher einstellen, d. SET @@group_concat_max_len = 32000;

+2

Der Kommentar am Ende zu "max_len" war ein Lebensretter! Danke für den Tipp. – Edward

+1

Wenn Sie nach dynamischeren Pivotabfragen suchen, überprüfen Sie dies bitte: http://www.boynux.com/creating-pivot-reports-in-mysql/ – Boynux

Verwandte Themen