在 SQL Server 2008 R2 中将行旋转成列
Pivoting rows into columns in SQL Server 2008 R2
我有一个table这样的
ProductID ValidFrom ValidTo Count
----------------------------------------
1 10/1/2015 20/12/2015 100
1 1/4/2014 31/12/2014 200
1 2/2/2013 20/9/2013 300
我需要这样的旋转结果
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 10/1/2015 to 20/12/2015 100 1/4/2014 to 31/12/2014 200 9/5/2014 to 20/9/2014 300
如果当前日期介于特定的 ValidFrom 和 ValidTo 之间,则它应显示在 CurrentYearValidity 列下。如果今天是 2015 年 3 月 26 日,那么如果 2014 年 3 月 26 日介于特定的 ValidFrom 和 ValidTo 之间,则它应该显示在 PreviousYearValidity 列下。相应的计数也应显示在适当的列下。
我试过这样的 case 语句,
select
ProductID,
[CurrentValidity] = case
when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
then (CONVERT(varchar(30),ValidFrom,110)+' to '+CONVERT(varchar(30),ValidTo,110))
else NULL
END,
[CurrentYearCount] = case
when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
then Count
else NULL
END,
[PreviousYearValidity] = case
when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
then (CONVERT(varchar(30),ValidFrom,110)+' to '+CONVERT(varchar(30),ValidTo,110))
else NULL
END,
[PreviousYearCount] = case
when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
then Count
else NULL
END
但是结果显示为
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 10/1/2015 to 20/12/2015 100
1 NULL NULL 1/4/2014 to 31/12/2014 200
1 NULL NULL NULL NULL 2/2/2013 to 20/9/2013 300
我想要视图中的结果。
请帮忙。
编辑:
如果 table 只有值
ProductID ValidFrom ValidTo Count
----------------------------------------
1 1/4/2014 31/12/2014 200
1 2/2/2013 20/9/2013 300
那么结果应该显示为
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 NULL NULL 1/4/2014 to 31/12/2014 200 2/2/2013 to 20/9/2013 300
@Giorgi Nakeuri 在这种情况下,您的查询失败。
对于您的查询,结果是,
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 1/4/2014 to 31/12/2014 200 2/2/2013 to 20/9/2013 300 NULL NULL
尝试:
DECLARE @t TABLE
(
ProductID INT ,
ValidFrom DATE ,
ValidTo DATE ,
Count INT
)
INSERT INTO @t
VALUES ( 1, '20150110', '20151220', 100 ),
( 1, '20140104', '20141231', 200 ),
( 1, '20130202', '20130920', 300 );
WITH cte1
AS ( SELECT ProductID ,
CAST(ValidFrom AS NVARCHAR(10)) AS ValidFrom ,
ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY ValidFrom DESC ) AS rn
FROM @t
),
cte2
AS ( SELECT ProductID ,
CAST(ValidTo AS NVARCHAR(10)) AS ValidTo ,
ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY ValidFrom DESC ) AS rn
FROM @t
),
cte3
AS ( SELECT ProductID ,
Count ,
ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY ValidFrom DESC ) AS rn
FROM @t
)
SELECT p1.ProductID ,
p1.[1] + ' to ' + p2.[1] AS CurrentYearValidity ,
p3.[1] AS CurrentYearCount ,
p1.[2] + ' to ' + p2.[2] AS PreviousYearValidity ,
p3.[2] AS PreviousYearCount ,
p1.[3] + ' to ' + p2.[3] AS PreviousTowYearsValidity ,
p3.[3] AS PreviousTwoYearCount
FROM ( SELECT *
FROM cte1 PIVOT( MAX(ValidFrom) FOR rn IN ( [1], [2], [3] ) ) p
) p1
JOIN ( SELECT *
FROM cte2 PIVOT( MAX(ValidTo) FOR rn IN ( [1], [2], [3] ) ) p
) p2 ON p2.ProductID = p1.ProductID
JOIN ( SELECT *
FROM cte3 PIVOT( MAX(Count) FOR rn IN ( [1], [2], [3] ) ) p
) p3 ON p3.ProductID = p2.ProductID
输出:
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 2015-01-10 to 2015-12-20 100 2014-01-04 to 2014-12-31 200 2013-02-02 to 2013-09-20 300
我有一个table这样的
ProductID ValidFrom ValidTo Count
----------------------------------------
1 10/1/2015 20/12/2015 100
1 1/4/2014 31/12/2014 200
1 2/2/2013 20/9/2013 300
我需要这样的旋转结果
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 10/1/2015 to 20/12/2015 100 1/4/2014 to 31/12/2014 200 9/5/2014 to 20/9/2014 300
如果当前日期介于特定的 ValidFrom 和 ValidTo 之间,则它应显示在 CurrentYearValidity 列下。如果今天是 2015 年 3 月 26 日,那么如果 2014 年 3 月 26 日介于特定的 ValidFrom 和 ValidTo 之间,则它应该显示在 PreviousYearValidity 列下。相应的计数也应显示在适当的列下。
我试过这样的 case 语句,
select
ProductID,
[CurrentValidity] = case
when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
then (CONVERT(varchar(30),ValidFrom,110)+' to '+CONVERT(varchar(30),ValidTo,110))
else NULL
END,
[CurrentYearCount] = case
when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
then Count
else NULL
END,
[PreviousYearValidity] = case
when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
then (CONVERT(varchar(30),ValidFrom,110)+' to '+CONVERT(varchar(30),ValidTo,110))
else NULL
END,
[PreviousYearCount] = case
when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
then Count
else NULL
END
但是结果显示为
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 10/1/2015 to 20/12/2015 100
1 NULL NULL 1/4/2014 to 31/12/2014 200
1 NULL NULL NULL NULL 2/2/2013 to 20/9/2013 300
我想要视图中的结果。
请帮忙。
编辑: 如果 table 只有值
ProductID ValidFrom ValidTo Count
----------------------------------------
1 1/4/2014 31/12/2014 200
1 2/2/2013 20/9/2013 300
那么结果应该显示为
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 NULL NULL 1/4/2014 to 31/12/2014 200 2/2/2013 to 20/9/2013 300
@Giorgi Nakeuri 在这种情况下,您的查询失败。 对于您的查询,结果是,
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 1/4/2014 to 31/12/2014 200 2/2/2013 to 20/9/2013 300 NULL NULL
尝试:
DECLARE @t TABLE
(
ProductID INT ,
ValidFrom DATE ,
ValidTo DATE ,
Count INT
)
INSERT INTO @t
VALUES ( 1, '20150110', '20151220', 100 ),
( 1, '20140104', '20141231', 200 ),
( 1, '20130202', '20130920', 300 );
WITH cte1
AS ( SELECT ProductID ,
CAST(ValidFrom AS NVARCHAR(10)) AS ValidFrom ,
ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY ValidFrom DESC ) AS rn
FROM @t
),
cte2
AS ( SELECT ProductID ,
CAST(ValidTo AS NVARCHAR(10)) AS ValidTo ,
ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY ValidFrom DESC ) AS rn
FROM @t
),
cte3
AS ( SELECT ProductID ,
Count ,
ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY ValidFrom DESC ) AS rn
FROM @t
)
SELECT p1.ProductID ,
p1.[1] + ' to ' + p2.[1] AS CurrentYearValidity ,
p3.[1] AS CurrentYearCount ,
p1.[2] + ' to ' + p2.[2] AS PreviousYearValidity ,
p3.[2] AS PreviousYearCount ,
p1.[3] + ' to ' + p2.[3] AS PreviousTowYearsValidity ,
p3.[3] AS PreviousTwoYearCount
FROM ( SELECT *
FROM cte1 PIVOT( MAX(ValidFrom) FOR rn IN ( [1], [2], [3] ) ) p
) p1
JOIN ( SELECT *
FROM cte2 PIVOT( MAX(ValidTo) FOR rn IN ( [1], [2], [3] ) ) p
) p2 ON p2.ProductID = p1.ProductID
JOIN ( SELECT *
FROM cte3 PIVOT( MAX(Count) FOR rn IN ( [1], [2], [3] ) ) p
) p3 ON p3.ProductID = p2.ProductID
输出:
ProductID CurrentYearValidity CurrentYearCount PreviousYearValidity PreviousYearCount PreviousTowYearsValidity PreviousTwoYearCount
1 2015-01-10 to 2015-12-20 100 2014-01-04 to 2014-12-31 200 2013-02-02 to 2013-09-20 300