Answer: To efficiently convert rows to columns in SQL Server you can use the PIVOT function.
It is important to convert rows into columns because it improves the performance and readability of the database. Converting rows into columns is called pivoting. In this blog, we will discuss different approaches to efficiently convert rows to columns in SQL Server and provide examples for each.
Table of Contents:
Methods to Convert Rows to Columns in SQL Server
Before going into the methods, let us first create an AnimalOffspring table that can be used as an example for the following methods.
– Creation of the table
CREATE TABLE AnimalOffspring (
Animal VARCHAR(50),
Offspring VARCHAR(50),
Count INT
);
– Inserting values into the table
INSERT INTO AnimalOffspring (Animal, Offspring, Count) VALUES
('Lion', 'Cub', 3),
('Elephant', 'Calf', 1),
('Dog', 'Puppy', 5),
('Cat', 'Kitten', 4),
('Horse', 'Foal', 2);
SELECT * FROM AnimalOffspring;
Output:
We created a database with animals and their respective offspring and inserted the count of them. SQL Server provides multiple methods to convert rows into columns. Following are some of the commonly used methods explained with examples:
Method 1: Using the PIVOT Operator in SQL Server
The PIVOT operator is used to convert rows into columns in SQL Server, which makes it easier to understand and perform well with indexes.
Example:
SELECT * FROM AnimalOffspring;
SELECT * FROM (
SELECT Animal, Offspring, Count FROM AnimalOffspring
) AS SourceTable
PIVOT (
SUM(Count) FOR Offspring IN ([Cub], [Calf], [Puppy], [Kitten], [Foal])
) AS PivotTable;
Output:
Explanation: This PIVOT operator first gathered the information on row count, animal, and offspring using SUM (count). Then the animals, their count, and their offspring are in the column, respectively.
Method 2: CASE with a THEN aggregate query in SQL Server
The CASE with THEN query will check the count and offspring to determine whether it is correct. If the offspring is correct, it will return the count; if it is wrong, then 0 will return instead.
Example:
SELECT
Animal,
SUM(CASE WHEN Offspring = 'Cub' THEN Count ELSE 0 END) AS Cub,
SUM(CASE WHEN Offspring = 'Calf' THEN Count ELSE 0 END) AS Calf,
SUM(CASE WHEN Offspring = 'Puppy' THEN Count ELSE 0 END) AS Puppy,
SUM(CASE WHEN Offspring = 'Kitten' THEN Count ELSE 0 END) AS Kitten,
SUM(CASE WHEN Offspring = 'Foal' THEN Count ELSE 0 END) AS Foal
FROM AnimalOffspring
GROUP BY Animal;
Output:
Explanation: The CASE with THEN counts the value of offspring; the ELSE statement checks whether the offspring has value if(offspring = Calf), here Calf has a certain count, so it returns the count. If it doesn’t have a count, then it will return 0.
Method 3: Using Dynamic SQL in SQL Server
The dynamic SQL in SQL Server helps to update automatically when the new AnimalOffspring exists. This method helps to update the new data. This reduces the time of manually updating it.
Example:
DECLARE @cols NVARCHAR(MAX), @query NVARCHAR(MAX);
-- Get distinct column values (Offspring types)
SELECT @cols = STRING_AGG(QUOTENAME(Offspring), ',') FROM (SELECT DISTINCT Offspring FROM AnimalOffspring) AS t;
SET @query = '
SELECT Animal, ' + @cols + '
FROM (
SELECT Animal, Offspring, Count FROM AnimalOffspring
) AS SourceTable
PIVOT (
SUM(Count) FOR Offspring IN (' + @cols + ')
) AS PivotTable;';
EXEC sp_executesql @query;
Output:
Explanation: The dynamic SQL has been applied to the table here, so if there are any new updates, it will automatically update it.
Method 4: Using multiple joins in SQL Server
Using multiple joins in SQL Server, rows can be converted to columns. You can use a combination of self-joins or inner joins.
Example:
SELECT DISTINCT a.Animal,
ISNULL(c.CubCount, 0) AS Cub,
ISNULL(ca.CalfCount, 0) AS Calf,
ISNULL(p.PuppyCount, 0) AS Puppy
FROM AnimalOffspring a
LEFT JOIN (
SELECT Animal, SUM(Count) AS CubCount
FROM AnimalOffspring
WHERE Offspring = 'Cub'
GROUP BY Animal
) c ON a.Animal = c.Animal
LEFT JOIN (
SELECT Animal, SUM(Count) AS CalfCount
FROM AnimalOffspring
WHERE Offspring = 'Calf'
GROUP BY Animal
) ca ON a.Animal = ca.Animal
LEFT JOIN (
SELECT Animal, SUM(Count) AS PuppyCount
FROM AnimalOffspring
WHERE Offspring = 'Puppy'
GROUP BY Animal
) p ON a.Animal = p.Animal;
Output:
Explanation: The multiple joins are useful here with the help of the left join, it fetches all the rows and converts them to columns.
Method 5: Using string agg() in SQL Server
The String agg() in SQL Server converts rows to columns by using the aggregate function Group By and conditional aggregation.
Example:
SELECT
Animal,
STRING_AGG(Offspring, ', ') AS Offspring_List
FROM AnimalOffspring
GROUP BY Animal;
Output:

Explanation: The String agg() function converts the string to columns using the aggregate function. This function concatenates multiple rows together into a single column.
Alternative Method to Convert Rows to Columns in SQL
Using CROSS TAB (case with MAX): This method uses the CASE function with Max query in SQL Server. It is not scalable. It does not use PIVOT or the dynamic method. The CROSS TAB method can be used for simpler data.
Example:
SELECT
Animal,
MAX(CASE WHEN Offspring = 'Cub' THEN Count ELSE NULL END) AS Cub,
MAX(CASE WHEN Offspring = 'Calf' THEN Count ELSE NULL END) AS Calf,
MAX(CASE WHEN Offspring = 'Puppy' THEN Count ELSE NULL END) AS Puppy,
MAX(CASE WHEN Offspring = 'Kitten' THEN Count ELSE NULL END) AS Kitten,
MAX(CASE WHEN Offspring = 'Foal' THEN Count ELSE NULL END) AS Foal
FROM AnimalOffspring
GROUP BY Animal;
Output:
Explanation: This will also produce the same output, but it will not use PIVOT or dynamic. It is an alternative method if we can’t use PIVOT.
Conclusion
Using the CROSS TAB method with CASE and MAX provides a simple way to convert rows into columns without relying on the PIVOT function. It works well for small datasets where the column values are known in advance. This approach ensures clarity and compatibility across different SQL versions. However, it requires manual updates if new column values appear, making it less scalable for dynamic datasets. While efficient for fixed categories, PIVOT or Dynamic SQL is a better choice for handling unknown or changing columns automatically.
FAQs
1. When should I use the PIVOT operator?
You should use the PIVOT operator to apply an aggregate function such as SUM or COUNT to convert rows into columns where the column names are fixed.
2. Why is Dynamic SQL useful for row-to-column conversion?
Dynamic SQL works when the number of columns is unknown. The pivot query during runtime, allows the dynamic datasets to be processed efficiently.
3. How does PIVOT differ from STRING_AGG()?
PIVOT will convert rows to columns through numeric aggregation. STRING_AGG() will combine multiple values into a single text string in a column.
4. When should I use CASE with aggregate functions instead of PIVOT?
Using CASE with aggregate functions when you need more custom logic or when working with databases that don’t support the PIVOT operator. It offers greater flexibility in handling complex conditions.
5. What are the drawbacks of using multiple joins for row-to-column conversion?
Using multiple joins often leads to very complicated queries affecting the performance of large datasets. They are ideal for smaller datasets or when the expected number of columns is fixed.