[英]Derive column name from date in rows and show monthly data in sql
我有一個如下表:
CREATE table #yourtable
(
[Id] int,
[ColumnName] varchar(13),
Val1 float,
Val2 float,
StartDate datetime,
EndDate datetime
);
INSERT INTO #yourtable
([Id], [ColumnName],Val1,Val2,StartDate,EndDate)
VALUES
(1,'ABC12',1000,900,'2016-01-01 00:00:00','2016-01-31 23:59:59'),
(2,'ABC12',1100,900,'2016-02-01 00:00:00','2016-02-29 23:59:59'),
(3,'CDE34',1000,800,'2016-01-01 00:00:00','2016-01-31 23:59:59'),
(4,'EFG45',1000,700,'2016-03-01 00:00:00','2016-03-31 23:59:59'),
(5,'FGH56',1000,1001,'2016-02-01 00:00:00','2016-02-29 23:59:59');
我正在嘗試獲取每月的隔離數據,如下所示:
Column Name Jan Feb Mar
ABC12 1000 1100 null
ABC12 900 900 null
CDE34 1000 null null
CDE34 800 null null
EFG45 null null 1000
EFG45 null null 700
FGH56 null 1000 null
FGH56 null 1001 null
我對sql比較陌生。 提前致謝
嘗試這個..
SELECT * FROM (SELECT [ColumnName],
SUM(Val1) AS _Val,
CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(StartDate), - 1))) MonthCol
FROM #yourtable WHERE YEAR(StartDate) = 2016
GROUP BY StartDate,[ColumnName]) AS TP
PIVOT (SUM(_Val) FOR MonthCol IN ([Jan], [Feb], [Mar], [Apr], [May], [Jun], [Jul], [Aug], [Sep], [Oct], [Nov], [Dec])) AS PVTTable
UNION
SELECT * FROM (SELECT [ColumnName],
SUM(Val2) AS _Val,
CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(EndDate), - 1))) MonthCol
FROM #yourtable WHERE YEAR(EndDate) = 2016
GROUP BY EndDate,[ColumnName]) AS TP
PIVOT (SUM(_Val) FOR MonthCol IN ([Jan], [Feb], [Mar], [Apr], [May], [Jun], [Jul], [Aug], [Sep], [Oct], [Nov], [Dec])) AS PVTTable
對於動態查詢
DECLARE @MaxMonth DATE = GETDATE();
DECLARE @YearData NVARCHAR(4) = CAST(YEAR(@MaxMonth) AS NVARCHAR(4))
DECLARE @END_MM INT = MONTH(@MaxMonth) --End of Month
DECLARE @START_MM INT = 1 --Start Month of Year Data
DECLARE @TB_DATE AS TABLE
(
ID INT IDENTITY(1,1),
MONTH_LIST VARCHAR(12)
)
WHILE @START_MM <= @END_MM
BEGIN
INSERT INTO @TB_DATE (MONTH_LIST) VALUES ('['+CONVERT(VARCHAR(3),DATENAME(MONTH, DATEADD(MONTH, @START_MM-1, CAST(@END_MM AS datetime))))+']')
SET @START_MM=@START_MM+1
END
DECLARE @MM_LIST NVARCHAR(MAX) = (SELECT STUFF((SELECT ',' + MONTH_LIST
FROM @TB_DATE ORDER BY ID DESC
FOR XML PATH('')) ,1,1,'') AS Txt)
DECLARE @DynamicPivot AS NVARCHAR(MAX)
SET @DynamicPivot = N' SELECT * FROM (SELECT [ColumnName],
SUM(Val1) AS _Val,
CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(StartDate), - 1))) MonthCol
FROM #yourtable WHERE YEAR(StartDate) = '+@YearData+'
GROUP BY StartDate,[ColumnName]) AS TP
PIVOT (SUM(_Val) FOR MonthCol IN ('+@MM_LIST+')) AS PVTTable
UNION
SELECT * FROM (SELECT [ColumnName],
SUM(Val2) AS _Val,
CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(EndDate), - 1))) MonthCol
FROM #yourtable WHERE YEAR(EndDate) = '+@YearData+'
GROUP BY EndDate,[ColumnName]) AS TP
PIVOT (SUM(_Val) FOR MonthCol IN ('+@MM_LIST+')) AS PVTTable';
EXEC sp_executesql @DynamicPivot
旋轉時 :
SELECT ColumnName,
MAX([Jan]) as [Jan],
MAX([Feb]) as [Feb],
MAX([Mar]) as [Mar],
MAX([Apr]) as [Apr],
MAX([May]) as [May],
MAX([Jun]) as [Jun],
MAX([Jul]) as [Jul],
MAX([Aug]) as [Aug]
FROM (
SELECT Id,
ColumnName,
LEFT(DATENAME(MONTH,StartDate),3) as M,
[Vals],
[Column]
FROM
(SELECT *
FROM #yourtable) y
UNPIVOT (
[Column] FOR Vals IN ([Val1],[Val2])
)as unpvt
) as s
PIVOT (
MAX([Column]) FOR M IN ([Jan],[Feb],[Mar],[Apr],[May],[Jun],[Jul],[Aug])
) as pvt
GROUP BY ColumnName,Vals
ORDER BY ColumnName
輸出:
ColumnName Jan Feb Mar
ABC12 1000 1100 NULL
ABC12 900 900 NULL
CDE34 1000 NULL NULL
CDE34 800 NULL NULL
EFG45 NULL NULL 1000
EFG45 NULL NULL 700
FGH56 NULL 1000 NULL
FGH56 NULL 1001 NULL
使用UNPIVOT,我們得到以下表格結構:
Id ColumnName M Vals Column
1 ABC12 Jan Val1 1000
1 ABC12 Jan Val2 900
2 ABC12 Feb Val1 1100
2 ABC12 Feb Val2 900
3 CDE34 Jan Val1 1000
3 CDE34 Jan Val2 800
4 EFG45 Mar Val1 1000
4 EFG45 Mar Val2 700
5 FGH56 Feb Val1 1000
5 FGH56 Feb Val2 1001
因此,所有Vals
都在一列中,然后我們在GROUP BY和ORDER BY的幫助下使用PIVOT獲得所需的結果。
如果有很多Vals
最好使用動態SQL。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.