How to Return Pivot Table Output in MySQL?

Pivot in SQL is helpful when you need to convert row-based data into columns to make the data easier to analyze. MySQL does not have built-in functions for PIVOT like SQL Server, but it can be used in MySQL by using CASE statements with aggregate functions or dynamic SQL with GROUP_CONCAT(). In this blog, let us explore the different methods by which we can return the Pivot Table as an output in MySQL

Table of Contents:

Let’s create a table and insert some values into it that can be used as an example for the following methods 

CREATE TABLE restaurant_ratings (
    restaurant_id INT AUTO_INCREMENT PRIMARY KEY,
    restaurant_name VARCHAR(100),
    city VARCHAR(50),
    rating INT
);
INSERT INTO restaurant_ratings (restaurant_name, city, rating) VALUES
('Gourmet Delight', 'New York', 5),
('Gourmet Delight', 'Los Angeles', 4),
('Gourmet Delight', 'Chicago', 3),
('Tasty Treats', 'New York', 4),
('Tasty Treats', 'Los Angeles', 5),
('Tasty Treats', 'Chicago', 3),
('Food Paradise', 'New York', 3),
('Food Paradise', 'Los Angeles', 4),
('Food Paradise', 'Chicago', 5);
SET @sql = NULL;
SELECT * FROM restaurant_ratings;
pivot_table_creation

This is how the table looks after creating and inserting the data.

Master the PIVOT in MySQL – Unlock Advanced SQL Skills Today!
Enroll now and transform your future!
quiz-icon

Methods to Return Pivot Table Output in MySQL

There are several methods to return pivot table output in MySQL, like using CASE with aggregate, dynamic PIVOT, cross-tabulation (organizing data in table) with joins, etc. 

Method 1: Using Dynamic Columns with GROUP_CONCAT in MySQL

Dynamic columns with GROUP_CONCAT() in MySQL are used in dynamically generated columns. It can be used when the names of the columns are known in advance. It is very efficient when we use tables that update dynamically. 

Example:

SET @sql = NULL;
SELECT 
    GROUP_CONCAT(DISTINCT 
        CONCAT(
            'MAX(CASE WHEN city = ''', city, ''' THEN rating ELSE NULL END) AS `', city, '`'
        )
    ) INTO @sql
FROM restaurant_ratings;
SET @sql = CONCAT('SELECT restaurant_name, ', @sql, ' FROM restaurant_ratings GROUP BY restaurant_name');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Output:

 Dynamic Columns with GROUP_CONCAT in MySQL

Explanation: The dynamic columns with GROUP_CONCAT() converted the output strings into columns for easier access. 

Method 2: Using CASE with aggregate functions in MySQL

The CASE inside an aggregate function like MAX(), SUM(), and GROUP BY returns the pivot table output in MySQL.

1. Using CASE with GROUP BY in MySQL

The CASE with GROUP BY in MySQL is the simplest way to pivot data when the column values are known. 

Example:

SELECT 
    city,
    CASE 
        WHEN AVG(rating) >= 4.5 THEN 'Excellent'
        WHEN AVG(rating) BETWEEN 3.5 AND 4.4 THEN 'Good'
        ELSE 'Average'
    END AS Rating_Category
FROM restaurant_ratings
GROUP BY city;

Output:

CASE with aggregate functions in MySQL

Explanation: Here, the CASE with the GROUP BY function gets the rating by conditioning the range of ratings and converting them into columns for easier access. 

2. Using SUM with CASE in MySQL

The SUM with CASE makes sure that aggregated data is distributed evenly. 

Example:

SELECT 
    restaurant_name,
    SUM(CASE WHEN city = 'New York' THEN rating ELSE 0 END) AS Total_New_York,
    SUM(CASE WHEN city = 'Los Angeles' THEN rating ELSE 0 END) AS Total_Los_Angeles,
    SUM(CASE WHEN city = 'Chicago' THEN rating ELSE 0 END) AS Total_Chicago
FROM restaurant_ratings
GROUP BY restaurant_name;

Output:

Using SUM with CASE in MySQL

Explanation: You can find the restaurant in each area by using SUM(), which combines the count of the restaurant. GROUP BY restaurant_name ensures that all SUM results are combined and pivoted.

3. Using MAX() with CASE in MySQL

The MAX() function gets the data. It does not require dynamic SQL. 

Example:

SELECT 
    restaurant_name,
    MAX(CASE WHEN city = 'New York' THEN rating ELSE NULL END) AS New_York,
    MAX(CASE WHEN city = 'Los Angeles' THEN rating ELSE NULL END) AS Los_Angeles,
    MAX(CASE WHEN city = 'Chicago' THEN rating ELSE NULL END) AS Chicago
FROM restaurant_ratings
GROUP BY restaurant_name;

Output:

Using MAX() with CASE in MySQL

Explanation: Here, the MAX() function acquires the data of ratings of each restaurant per city. 

Get 100% Hike!

Master Most in Demand Skills Now!

Method 3: Cross Tabulation Methods with Joins function in MySQL

The Cross Tabulation Method is an alternative method to return output like PIVOT. It will not use aggregate functions like GROUP BY or SUM(). This method uses joins like self-joins and cross-joins that convert rows into column format. 

1. Using Self-JOIN 

You can use the joins with the table itself and can filter it based on the conditions specified. The self-join extracts the specific data. It can work efficiently when the table is smaller. 

Example:

SELECT r1.restaurant_name,
       r1.rating AS New_York,
       r2.rating AS Los_Angeles,
       r3.rating AS Chicago
FROM restaurant_ratings r1
LEFT JOIN restaurant_ratings r2 
    ON r1.restaurant_name = r2.restaurant_name 
    AND r2.city = 'Los Angeles'
LEFT JOIN restaurant_ratings r3 
    ON r1.restaurant_name = r3.restaurant_name 
    AND r3.city = 'Chicago'
WHERE r1.city = 'New York';

Output:

Cross Tabulation Methods with Joins_Self-JOIN

Explanation: Here, the self-join assigns the rows with r1, r2, and r3 for restaurants in New York, Los Angeles, and Chicago, respectively and extracts ratings from them. The left join makes sure that the NULL value is not eliminated. 

2. Using Cross Join with Aggregation

The Cross join produces a product that is cartesian and helps in structured transformation, then uses an aggregate function like MAX() to pivot the values. 

Example:

SELECT 
    r.restaurant_name,
    MAX(CASE WHEN c.city = 'New York' THEN r.rating ELSE NULL END) AS New_York,
    MAX(CASE WHEN c.city = 'Los Angeles' THEN r.rating ELSE NULL END) AS Los_Angeles,
    MAX(CASE WHEN c.city = 'Chicago' THEN r.rating ELSE NULL END) AS Chicago
FROM restaurant_ratings r
CROSS JOIN (SELECT DISTINCT city FROM restaurant_ratings) c
GROUP BY r.restaurant_name;

Output:

Cross Join with Aggregation

Explanation: Here, the cross-join creates a matrix structure temporarily with cities and restaurants, then CASE with MAX() combines the data into columns, and then GROUP BY displays the table. 

Alternative Dynamic SQL for Unknown Column Values

You can use the dynamic tables where the value of columns updates over time. But in this we cannot use the CASE statement, so instead we can use the GROUP_CONCAT() and PREPARE statements.

Example:

CREATE TABLE sales (
    product VARCHAR(100),
    year INT,
    sales DECIMAL(10,2)
);
INSERT INTO sales (product, year, sales) VALUES
('Laptop', 2022, 50000),
('Laptop', 2023, 60000),
('Phone', 2022, 30000),
('Phone', 2023, 40000),
('Tablet', 2022, 20000),
('Tablet', 2023, 25000);
SET @sql = NULL;
SELECT 
    GROUP_CONCAT(DISTINCT 
        CONCAT('SUM(CASE WHEN year = ', year, ' THEN sales ELSE 0 END) AS `', year, ' Sales`')
    ) INTO @sql
FROM sales;
SET @sql = CONCAT('SELECT product, ', @sql, ' FROM sales GROUP BY product');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Output:

Alternative Dynamic SQL for Unknown Column Values

Explanation: Here, the GROUP_CONCAT fetches the dynamic unique year values and creates a pivot column. The PREPARE statement compiles and executes the query. 

Performance Comparison

Method Execution Speed Flexibility Best Use Case Complexity
CASE with Aggregate Functions Fast because it uses indexed values. Low flexibility because of fixed columns. Can be used for small tables with fixed pivot columns. Easy to use and read.
GROUP_CONCAT() with Dynamic SQL Moderate as there is a compilation in query overhead Flexible, as it can handle unknown columns. Dynamic dataset with column values that change over time. It is complex as it needs to fetch the data dynamically.
Self-JOIN – Cross Tabulation It has to perform a join operation within the table, so the performance will be low. Flexibility is low. Best when it is used in small datasets. Medium complexity.
CROSS JOIN with Aggregation Fast because it uses indexed columns. Flexibility is low because of fixed columns. It works best with large datasets and structured data. Medium complexity
Dynamic SQL for Unknown Columns Moderate due to slow query overhead. Flexibility is high as it adjusts itself with new data. The best case is when the pivot values are added dynamically. It is very complex.

Real World Examples

Case 1: The meteorological department collects daily temperature data from different stations. The PIVOT will collect all the data and display it in columnar format. 

Example:

CREATE TABLE weather_data (
    station_id INT AUTO_INCREMENT PRIMARY KEY,
    station_name VARCHAR(100),
    date DATE,
    temperature DECIMAL(5,2)
);
INSERT INTO weather_data (station_name, date, temperature) VALUES
('Station A', '2024-03-01', 15.0),
('Station A', '2024-03-02', 18.0),
('Station B', '2024-03-01', 20.0),
('Station B', '2024-03-03', 22.0);
SELECT 
    station_name,
    MAX(CASE WHEN date = '2024-03-01' THEN temperature ELSE NULL END) AS "March 1",
    MAX(CASE WHEN date = '2024-03-02' THEN temperature ELSE NULL END) AS "March 2",
    MAX(CASE WHEN date = '2024-03-03' THEN temperature ELSE NULL END) AS "March 3"
FROM weather_data
GROUP BY station_name;

Output:

real_world_example_daily_temperature_data

Explanation: Here, the pivot shows the temperature changes from different stations for different days.

Case 2: Movie streaming analytics

In the movie streaming platform, we need to fetch the records of monthly watch time per genre for users. We need to pivot the data to evaluate the monthly genre-wise trend. 

Example:

CREATE TABLE watch_time (
    user_id INT,
    genre VARCHAR(50),
    month VARCHAR(7),  
    hours_watched INT
);
INSERT INTO watch_time (user_id, genre, month, hours_watched) VALUES
(101, 'Action', '2024-02', 10),
(101, 'Comedy', '2024-02', 5),
(102, 'Action', '2024-02', 7),
(101, 'Action', '2024-03', 12),
(102, 'Comedy', '2024-03', 8);
INSERT INTO watch_time (user_id, genre, month, hours_watched) VALUES
(102, 'Horror', '2024-03', 23);
SET @sql = NULL;
SELECT 
    GROUP_CONCAT(DISTINCT 
        CONCAT('SUM(CASE WHEN month = ''', month, ''' THEN hours_watched ELSE 0 END) AS `', month, '`')
    ) INTO @sql
FROM watch_time;
SET @sql = CONCAT('SELECT genre, ', @sql, ' FROM watch_time GROUP BY genre');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Output:
real_world_example_movie_streaming_analysis

Explanation: Using dynamic SQL with the PREPARE statement, we fetched the data of monthly records of genres watched by the user. 

Start Your SQL Adventure!
Start Your SQL Journey for Free Today
quiz-icon

Conclusion

To convert rows into columns, you can use PIVOT in MySQL, which makes the data more readable in a tabular format that will make you analyze the data more easily. Since MySQL doesn’t have a built-in PIVOT function like SQL Server, it uses approaches like CASE with aggregate functions, dynamic SQL with GROUP_BY CONCAT(), PREPARE statements for dynamic column values, and the cross-tabulation method with self-join and cross-join. Based on the dataset, you can choose the best technique to get the desired output. 

You can learn more about SQL in the SQL Course and also explore SQL Interview Questions prepared by industry experts.

How to Return Pivot Table Output in MySQL – FAQs

Q1. How to see table output in MySQL?

Use SELECT * FROM table_name; to view the table’s data.

Q2. How to use a pivot table in MySQL?

Use CASE statements with aggregate functions or dynamic SQL with GROUP_CONCAT() to pivot data.

Q3. How do you convert a pivot table back to a table?

Use UNPIVOT logic by selecting data using UNION ALL or restructuring with JOINs.

Q4. How do I return a Pivot Table?

Use SQL queries with CASE, GROUP BY, and aggregate functions to structure pivoted data.

Q5. How do I get back a PivotTable field?

Retrieve specific pivot fields using column selection in SELECT statements based on your pivot logic.

About the Author

Data Engineer

As a skilled Data Engineer, Sahil excels in SQL, NoSQL databases, Business Intelligence, and database management. He has contributed immensely to projects at companies like Bajaj and Tata. With a strong expertise in data engineering, he has architected numerous solutions for data pipelines, analytics, and software integration, driving insights and innovation.

business intelligence professional