add batch remove batch split batch comment selection show hidden batches hide batch highlight batch
db<>fiddle
donate feedback about
By using db<>fiddle, you agree to license everything you submit by Creative Commons CC0.
select @@version;CREATE TABLE Data (
Country VARCHAR(100),
sales_date DATE,
sales_code VARCHAR(100),
type_item VARCHAR(100),
sales INT
)
INSERT Data
VALUES
('Algeria', '2024-06-01', 'ACTUAL', 'Hat', 200),
('Algeria', '2024-06-01', 'ACTUAL', 'Shirt', 145),
('Algeria', '2024-06-01', 'ACTUAL', 'Pant', 150),
('Algeria', '2024-06-01', 'TARGET', 'Hat', 90),
('Algeria', '2024-06-01', 'TARGET', 'Shirt', 500),
('Algeria', '2024-06-01', 'TARGET', 'Pant', 100)

(No column name)
Microsoft SQL Server 2017 (RTM-CU30) (KB5013756) - 14.0.3451.2 (X64)
Jun 22 2022 18:20:15
Copyright (C) 2017 Microsoft Corporation
Express Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64> (Build 17763: ) (Hypervisor)
-- Using a compound pivot axis PIVOT
SELECT PVT.*
FROM (
SELECT
Country, sales_date, sales,
CONCAT(type_item, '_sales_', sales_code) AS Combined
FROM Data
) D
PIVOT (
SUM(sales)
FOR Combined IN (
hat_sales_ACTUAL, hat_sales_TARGET,
shirt_sales_ACTUAL, shirt_sales_TARGET,
pant_sales_ACTUAL, pant_sales_TARGET
)
) PVT

Country sales_date hat_sales_ACTUAL hat_sales_TARGET shirt_sales_ACTUAL shirt_sales_TARGET pant_sales_ACTUAL pant_sales_TARGET
Algeria 2024-06-01 200 90 145 500 150 100
-- Using COnditional Aggregation
SELECT
Country, sales_date,
SUM(CASE WHEN sales_code = 'ACTUAL' AND type_item = 'Hat' THEN sales ELSE 0 END)
AS hat_sales_ACTUAL,
SUM(CASE WHEN sales_code = 'TARGET' AND type_item = 'Hat' THEN sales ELSE 0 END)
AS hat_sales_TARGET,
SUM(CASE WHEN sales_code = 'ACTUAL' AND type_item = 'Shirt' THEN sales ELSE 0 END)
AS shirt_sales_ACTUAL,
SUM(CASE WHEN sales_code = 'TARGET' AND type_item = 'Shirt' THEN sales ELSE 0 END)
AS shirt_sales_TARGET,
SUM(CASE WHEN sales_code = 'ACTUAL' AND type_item = 'Pant' THEN sales ELSE 0 END)
AS pant_sales_ACTUAL,
SUM(CASE WHEN sales_code = 'TARGET' AND type_item = 'Pant' THEN sales ELSE 0 END)
AS pant_sales_TARGET
FROM Data
GROUP BY Country, sales_date
Country sales_date hat_sales_ACTUAL hat_sales_TARGET shirt_sales_ACTUAL shirt_sales_TARGET pant_sales_ACTUAL pant_sales_TARGET
Algeria 2024-06-01 200 90 145 500 150 100
-- Using dynamic SQL (SQL Server 2017 and later)
DECLARE @PivotForInList NVARCHAR(MAX) = (
SELECT STRING_AGG(QUOTENAME(CONCAT(type_item, '_sales_', sales_code)), ', ')
WITHIN GROUP(ORDER BY type_item, sales_code)
FROM (SELECT DISTINCT type_item FROM Data) D1
CROSS JOIN (SELECT DISTINCT sales_code FROM Data) D2
)

DECLARE @Sql NVARCHAR(MAX) = '
SELECT PVT.*
FROM (
SELECT
Country, sales_date, sales,
CONCAT(type_item, ''_sales_'', sales_code) AS Combined
FROM Data
) D
PIVOT (
SUM(sales)
FOR Combined IN (' + @PivotForInList + ')
) PVT
'

PRINT @Sql
EXEC (@Sql)
Country sales_date Hat_sales_ACTUAL Hat_sales_TARGET Pant_sales_ACTUAL Pant_sales_TARGET Shirt_sales_ACTUAL Shirt_sales_TARGET
Algeria 2024-06-01 200 90 150 100 145 500

SELECT PVT.*
FROM (
    SELECT
        Country, sales_date, sales,
        CONCAT(type_item, '_sales_', sales_code) AS Combined
    FROM Data
) D
PIVOT (
    SUM(sales)
    FOR Combined IN ([Hat_sales_ACTUAL], [Hat_sales_TARGET], [Pant_sales_ACTUAL], [Pant_sales_TARGET], [Shirt_sales_ACTUAL], [Shirt_sales_TARGET])
) PVT


-- Using dynamic SQL (Older SQL Server versions)
-- Uses teh FOR XML technique as a substitute for STRING_AGG()
DECLARE @PivotForInList NVARCHAR(MAX) = STUFF((
SELECT ', ' + QUOTENAME(CONCAT(type_item, '_sales_', sales_code))
FROM (SELECT DISTINCT type_item FROM Data) D1
CROSS JOIN (SELECT DISTINCT sales_code FROM Data) D2
ORDER BY type_item, sales_code
FOR XML PATH(''), TYPE
).value('.', 'varchar(max)'), 1, 2, '')

DECLARE @Sql NVARCHAR(MAX) = '
SELECT PVT.*
FROM (
SELECT
Country, sales_date, sales,
CONCAT(type_item, ''_sales_'', sales_code) AS Combined
FROM Data
) D
PIVOT (
SUM(sales)
FOR Combined IN (' + @PivotForInList + ')
) PVT
'

PRINT @Sql
EXEC (@Sql)
Country sales_date Hat_sales_ACTUAL Hat_sales_TARGET Pant_sales_ACTUAL Pant_sales_TARGET Shirt_sales_ACTUAL Shirt_sales_TARGET
Algeria 2024-06-01 200 90 150 100 145 500

SELECT PVT.*
FROM (
    SELECT
        Country, sales_date, sales,
        CONCAT(type_item, '_sales_', sales_code) AS Combined
    FROM Data
) D
PIVOT (
    SUM(sales)
    FOR Combined IN ([Hat_sales_ACTUAL], [Hat_sales_TARGET], [Pant_sales_ACTUAL], [Pant_sales_TARGET], [Shirt_sales_ACTUAL], [Shirt_sales_TARGET])
) PVT