简体   繁体   中英

How to pivot 3 rows to 3 columns

After a lot of effort and help I have arrived to download the Azure Retail Price list.

For every resource I have the unitPrice and the price for 1 Year and 3 Years:

currencyCode retailPrice unitPrice location meterId meterName skuId productName serviceId unitOfMeasure type isPrimaryMeterRegion reservationTerm
CHF 2739.0533 2739.0533 EU West 7766bed4-f4db-4593-9cc5-ebff48957117 D4 v3/D4s v3 DZH318Z0BQ4K/003T Virtual Machines Dv3 Series DZH313Z7MMC8 1 Hour Reservation True 3 Years
CHF 0.2376 0.2376 EU West 7766bed4-f4db-4593-9cc5-ebff48957117 D4 v3/D4s v3 DZH318Z0BQ4K/00S9 Virtual Machines Dv3 Series DZH313Z7MMC8 1 Hour Consumption True NULL
CHF 1325.4761 1325.4761 EU West 7766bed4-f4db-4593-9cc5-ebff48957117 D4 v3/D4s v3 DZH318Z0BQ4K/003S Virtual Machines Dv3 Series DZH313Z7MMC8 1 Hour Reservation True 1 Year

I would like to pivot the unitPrice where the reservationTerm is 1Year and 3 Years and obtain something like this:

currencyCode retailPrice unitPrice location meterId meterName skuId productName serviceId unitOfMeasure type isPrimaryMeterRegion reservationTerm unitPrice_Hour 3Years_Reservation 3Year_Reservation
CHF 2739.0533 2739.0533 EU West 7766bed4-f4db-4593-9cc5-ebff48957117 D4 v3/D4s v3 DZH318Z0BQ4K/003T Virtual Machines Dv3 Series DZH313Z7MMC8 1 Hour Reservation True 3 Years
CHF 0.2376 0.2376 EU West 7766bed4-f4db-4593-9cc5-ebff48957117 D4 v3/D4s v3 DZH318Z0BQ4K/00S9 Virtual Machines Dv3 Series DZH313Z7MMC8 1 Hour Consumption True NULL 0.2376 1325.4761 2739.0533
CHF 1325.4761 1325.4761 EU West 7766bed4-f4db-4593-9cc5-ebff48957117 D4 v3/D4s v3 DZH318Z0BQ4K/003S Virtual Machines Dv3 Series DZH313Z7MMC8 1 Hour Reservation True 1 Year

I followed a few guides and I ended up creating this test script:

SELECT TOP (1000) [currencyCode]
    ,[retailPrice]
    ,[unitPrice]
    ,[location]
    ,[meterId]
    ,[meterName]
    ,[skuId]
    ,[productName]
    ,[serviceId]
    ,[unitOfMeasure]
    ,[type]
    ,[isPrimaryMeterRegion]
    ,[reservationTerm]
FROM [dbo].[Azure_Retail_Prices]
WHERE meterId = '7766bed4-f4db-4593-9cc5-ebff48957117'
    AND isPrimaryMeterRegion != 'False'
pivot(MAX(unitPrice) FOR reservationTerm IN (
            NULL
            ,'1 Year'
            ,'3 Years'
            )) AS piv;

But it returns the error:

Incorrect syntax near the keyword 'pivot'.

What am I doing wrong?

You can create the table this way:

/****** Object:  Table [dbo].[Testing]    Script Date: 11/22/2022 12:49:11 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Testing](
    [currencyCode] [nvarchar](250) NULL,
    [retailPrice] [nvarchar](250) NULL,
    [unitPrice] [nvarchar](250) NULL,
    [location] [nvarchar](250) NULL,
    [meterId] [nvarchar](250) NULL,
    [meterName] [nvarchar](250) NULL,
    [skuId] [nvarchar](250) NULL,
    [productName] [nvarchar](250) NULL,
    [serviceId] [nvarchar](250) NULL,
    [unitOfMeasure] [nvarchar](250) NULL,
    [type] [nvarchar](250) NULL,
    [isPrimaryMeterRegion] [nvarchar](250) NULL,
    [reservationTerm] [nvarchar](250) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[Testing] ([currencyCode], [retailPrice], [unitPrice], [location], [meterId], [meterName], [skuId], [productName], [serviceId], [unitOfMeasure], [type], [isPrimaryMeterRegion], [reservationTerm]) VALUES (N'CHF', N'2739.0533', N'2739.0533', N'EU West', N'7766bed4-f4db-4593-9cc5-ebff48957117', N'D4 v3/D4s v3', N'DZH318Z0BQ4K/003T', N'Virtual Machines Dv3 Series', N'DZH313Z7MMC8', N'1 Hour', N'Reservation', N'True', N'3 Years')
GO
INSERT [dbo].[Testing] ([currencyCode], [retailPrice], [unitPrice], [location], [meterId], [meterName], [skuId], [productName], [serviceId], [unitOfMeasure], [type], [isPrimaryMeterRegion], [reservationTerm]) VALUES (N'CHF', N'0.2376', N'0.2376', N'EU West', N'7766bed4-f4db-4593-9cc5-ebff48957117', N'D4 v3/D4s v3', N'DZH318Z0BQ4K/00S9', N'Virtual Machines Dv3 Series', N'DZH313Z7MMC8', N'1 Hour', N'Consumption', N'True', NULL)
GO
INSERT [dbo].[Testing] ([currencyCode], [retailPrice], [unitPrice], [location], [meterId], [meterName], [skuId], [productName], [serviceId], [unitOfMeasure], [type], [isPrimaryMeterRegion], [reservationTerm]) VALUES (N'CHF', N'1325.4761', N'1325.4761', N'EU West', N'7766bed4-f4db-4593-9cc5-ebff48957117', N'D4 v3/D4s v3', N'DZH318Z0BQ4K/003S', N'Virtual Machines Dv3 Series', N'DZH313Z7MMC8', N'1 Hour', N'Reservation', N'True', N'1 Year')
GO

EDIT: After your comment I tried to wrap it up and I did this:

SELECT *
FROM (
    SELECT *
    FROM [dbo].[Azure_Retail_Prices]
    ) AS t
pivot(MAX(unitPrice) FOR reservationTerm IN (
            NULL
            ,'1 Year'
            ,'3 Years'
            )) AS p;

but it says Incorrect syntax near the keyword 'NULL'. . I don't see where the error is...

EDIT 2:

I tried with conditional aggregation but it's not working:

SELECT TOP 1000 [unitPrice]
    ,[meterId]
    ,[reservationTerm]
    ,CASE 
        WHEN reservationTerm = '3 Years'
            THEN unitPrice
        WHEN reservationTerm = '1 Years'
            THEN unitPrice
        ELSE 'hello'
        END
FROM [dbo].[Azure_Retail_Prices]
WHERE isPrimaryMeterRegion != 'False'
GROUP BY meterId
    ,[unitPrice]
    ,reservationTerm

在此处输入图像描述

The idea is to generate 1 column for the 3 years and 1 column for the 1 year.

EDIT 3: Following @Larnu link I put in place 2 different approach here: PIVOT and Aggregation:

/* Example with PIVOT */
SELECT 
    P.[meterId]
    ,P.[3 Years]
    ,P.[1 Year]
FROM (select * from [dbo].[Azure_Retail_Prices]
WHERE meterId = '7766bed4-f4db-4593-9cc5-ebff48957117'
    AND isPrimaryMeterRegion != 'False'
)V 
PIVOT (sum(unitPrice) FOR reservationTerm IN ([3 Years],[1 Year])) P

/* Example with Aggregation */
SELECT 
    [meterId]
    ,(CASE WHEN reservationTerm = '3 Years' THEN unitPrice ELSE '' END) as [3 Years]
    ,(CASE WHEN reservationTerm = '1 Year'  THEN unitPrice ELSE '' END) as [1 Years]
    ,(CASE WHEN reservationTerm = NULL  THEN unitPrice ELSE '' END) as [Is_Null]
FROM (select * from [dbo].[Azure_Retail_Prices]
WHERE meterId = '7766bed4-f4db-4593-9cc5-ebff48957117'
    AND isPrimaryMeterRegion != 'False'
)V 

But none of the two is working; they are returning the prices on different rows:

在此处输入图像描述

Thanks a millions to @Larnu that linked me this do-it-your-own link:

/* Example with PIVOT */
SELECT 
    P.[meterId]
    ,P.[3 Years]
    ,P.[1 Year]
FROM (select * from [dbo].[Azure_Retail_Prices]
WHERE meterId = '7766bed4-f4db-4593-9cc5-ebff48957117'
    AND isPrimaryMeterRegion != 'False'
)V 
PIVOT (sum(unitPrice) FOR reservationTerm IN ([3 Years],[1 Year])) P


/* Example with Aggregation */
SELECT 
    [meterId]
    ,max(CASE WHEN reservationTerm = '3 Years' THEN unitPrice ELSE '' END) as [3 Years]
    ,max(CASE WHEN reservationTerm = '1 Year'   THEN unitPrice ELSE '' END) as [1 Years]
    ,max(CASE WHEN reservationTerm IS NULL  THEN unitPrice ELSE '' END) as [Is_Null]
FROM (select * from [dbo].[Azure_Retail_Prices]
WHERE meterId = '7766bed4-f4db-4593-9cc5-ebff48957117'
    AND isPrimaryMeterRegion != 'False'
)V 
group by [meterId]

在此处输入图像描述

I still have some problems with PIVOT but the aggregation works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM