MySQL Pivot Table Query: Using Dynamic Columns for Data Analysis
P粉101708623
P粉101708623 2023-08-22 11:54:19
0
2
683
<p>I am using the following table to store product data: </p> <pre class="brush:php;toolbar:false;">mysql> SELECT * FROM product; --------------- --------------- -------- | id | name | description | stock | --------------- --------------- -------- | 1 | product1 | first product | 5 | | 2 | product2 | second product| 5 | --------------- --------------- -------- mysql> SELECT * FROM product_additional; --------------- ---------- | id | fieldname | fieldvalue | --------------- ---------- | 1 | size | S | | 1 | height | 103 | | 2 | size | L | | 2 | height | 13 | | 2 | color | black | ------------------ ------------ </pre> <p>Use the following query to select records from both tables: </p> <pre class="brush:php;toolbar:false;">mysql> SELECT p.id ,p.name , p.description ,MAX(IF(pa.fieldname = 'size', pa.fieldvalue, NULL)) as `size` ,MAX(IF(pa.fieldname = 'height', pa.fieldvalue, NULL)) as `height` ,MAX(IF(pa.fieldname = 'color', pa.fieldvalue, NULL)) as `color` FROM product p LEFT JOIN product_additional AS pa ON p.id = pa.id GROUP BY p.id --------------- --------------- -------- ---------- --- ----- | id | name | description | size | height | color | --------------- --------------- -------- ---------- --- ----- | 1 | product1 | first product | S | 103 | null | | 2 | product2 | second product| L | 13 | black | --------------- --------------- -------- ---------- --- ----- </pre> <p>Everything works fine :) </p> <p>Since I am populating the "additional" table dynamically, it would be nice if the query was also dynamic. This way I don't have to change the query every time I enter a new field name and field value. </p>
P粉101708623
P粉101708623

reply all(2)
P粉046387133

I have a slightly different way of accomplishing this than the accepted answer. This approach avoids using GROUP_CONCAT which has a 1024 character limit by default and won't work if you have a lot of fields unless you change the limit.

SET @sql = '';
SELECT
    @sql := CONCAT(@sql,if(@sql='','',', '),temp.output)
FROM
(
    SELECT
      DISTINCT
        CONCAT(
         'MAX(IF(pa.fieldname = ''',
          fieldname,
          ''', pa.fieldvalue, NULL)) AS ',
          fieldname
        ) as output
    FROM
        product_additional
) as temp;

SET @sql = CONCAT('SELECT p.id
                    , p.name
                    , p.description, ', @sql, ' 
                   FROM product p
                   LEFT JOIN product_additional AS pa 
                    ON p.id = pa.id
                   GROUP BY p.id, p.name, p.description');

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

Click here to view the demo

P粉768045522

In MySQL, the only way to do this dynamically is to use prepared statements. Here is a good article about them:

Dynamic pivot table (convert rows to columns)

Your code will look like this:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(IF(pa.fieldname = ''',
      fieldname,
      ''', pa.fieldvalue, NULL)) AS ',
      fieldname
    )
  ) INTO @sql
FROM product_additional;

SET @sql = CONCAT('SELECT p.id
                    , p.name
                    , p.description, ', @sql, ' 
                   FROM product p
                   LEFT JOIN product_additional AS pa 
                    ON p.id = pa.id
                   GROUP BY p.id, p.name, p.description');

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

ViewDemo

Note: The character limit of the GROUP_CONCAT function is 1024 characters. See parameter group_concat_max_len

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template