MySQL Pivot-Zeile in dynamische Anzahl von Spalten


81

Nehmen wir an, ich habe drei verschiedene MySQL-Tabellen:

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 Partnern in den Zeilen und Produkten 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

Verwenden dieser Abfrage:

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 hätte stattdessen gerne etwas wie:

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, sodass sich die Spaltennummer abhängig von den Zeilen in der Produkttabelle dynamisch ändern muss.

Diese sehr gute Antwort scheint mit MySQL nicht zu funktionieren: T-SQL Pivot? Möglichkeit zum Erstellen von Tabellenspalten aus Zeilenwerten


Weitere Vorschläge finden Sie unter Link Zeile zu Spalte .
Bhavin Pokiya


@BhavinPokiya, ein von Ihnen bereitgestellter MS SQL-Server-Link, der als MySQL gekennzeichnet ist.
MattSom

Antworten:


107

Leider hat MySQL keine PIVOTFunktion, die im Grunde das ist, was Sie versuchen zu tun. Sie müssen also eine Aggregatfunktion mit einer CASEAnweisung verwenden:

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-Demo

Da Sie die Produkte nicht kennen, möchten Sie dies wahrscheinlich dynamisch durchführen. Dies kann mit vorbereiteten Anweisungen erfolgen.

Bei dynamischen Pivot-Tabellen (Zeilen in Spalten umwandeln) würde Ihr Code folgendermaßen 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-Demo

Es ist wahrscheinlich erwähnenswert, dass dies GROUP_CONCATstandardmäßig auf 1024 Bytes beschränkt ist. Sie können dies umgehen, indem Sie es für die Dauer Ihres Verfahrens höher einstellen, d. H.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 Pivot-Abfragen suchen, überprüfen Sie dies bitte: boynux.com/creating-pivot-reports-in-mysql
Boynux

Was passiert, wenn der Produktname lautetProductA') from partners pt; truncate partners;
avatarofhope2

@ avatarofhope2 Ist das eine Frage oder eine Implikation? Wenn dies einen Einspritzwinkel ergibt, wie ist der richtige Umgang damit?
MattSom
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.