您将不得不使用动态SQL来实现所需的结果,因为数据集应该在其上执行的可能值在执行时未知。您还在多个列上进行转换[Observation]
& [Observer]
这意味着您将不得不使用CASE
语句和GROUP BY
子句,或者将所涉及的两个列组合到单个数据透视值列中。这个查询进一步复杂化的事实是,[Type]
似乎会影响结果应该如何显示。
我已经创建了一个如何在下面实现所需结果的示例。我提出以下假设:
例子:
-- Create some sample data
DECLARE @Observations TABLE
(
[Name] NVARCHAR(50) NOT NULL
,[Building] NVARCHAR(50) NOT NULL
,[Observation] DATETIME
,[Observer] NVARCHAR(50) NOT NULL
,[Type] INT
);
INSERT INTO @Observations
SELECT 'Doe, John', 'HQ', '01/01/2017', 'Doe, Jack', 1 UNION ALL
SELECT 'Doe, John', 'HQ', '02/01/2017', 'Doe, Jack', 1 UNION ALL
SELECT 'Doe, John', 'HQ', '03/01/2017', 'Doe, Jack', 2 UNION ALL
SELECT 'Doe, John', 'HQ', '04/01/2017', 'Doe, Jack', 1 UNION ALL
SELECT 'Doe, John', 'HQ', '05/01/2017', 'Doe, Jack', 1 UNION ALL
SELECT 'Doe, John', 'HQ', '06/01/2017', 'Doe, Jack', 3 UNION ALL
SELECT 'Doe, John', 'HQ', '07/01/2017', 'Doe, Jack', 6;
DECLARE @columns NVARCHAR(MAX) = N'';
DECLARE @selectClause NVARCHAR(MAX) = N'';
DECLARE @sql NVARCHAR(MAX);
CREATE TABLE #IntermResults
(
[Name] NVARCHAR(50) NOT NULL
,[Building] NVARCHAR(50) NOT NULL
,[PivotValue] NVARCHAR(50) NOT NULL
,[PivotID] NVARCHAR(50) NOT NULL
,[Observation] DATETIME NOT NULL
,[OrderRank] INT NOT NULL
)
-- Prepare the source data to make pivoting into desired format easier and store results into an interim temporary table.
;WITH ObservationsCTE
AS
(
SELECT [Name]
,[Building]
,[Observation]
,[Observer]
,[Type]
,(
CASE [Type]
WHEN 1 THEN 'Observation'
WHEN 2 THEN 'Interim'
WHEN 3 THEN 'Summative'
WHEN 6 THEN 'Overall'
ELSE 'UNKNOW'
END
) AS [ObservationType] -- Give descriptive values to Type column’s values. This will be used to help generate pivot table column names.
FROM @Observations
), ObservationsWithPivotIDs
AS
(
SELECT TOP 1000
[Name]
,[Building]
,CAST([Observation] AS NVARCHAR(50)) AS [PivotValue] -- Pivot value effectively combines the Observation & Observer column to help simplify the pivot query.
,'Observation' + CAST(ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY [Observation]) AS NVARCHAR(10)) AS [PivotID] -- Create a pivot id that will be used to generate pivoted columns.
,[Observation]
,1 AS [OrderRank] -- use this field to help order records.
FROM ObservationsCTE
WHERE [Type] = 1
UNION ALL
SELECT TOP 1000
[Name]
,[Building]
,[Observer] AS [PivotValue] -- Pivot value effectively combines the Observation & Observer column to help simplify the pivot query.
,'Observer' + CAST(ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY [Observation]) AS NVARCHAR(10)) AS [PivotID] -- Create a pivot id that will be used to generate pivoted columns.
,[Observation]
,2 AS [OrderRank] -- use this field to help order records.
FROM ObservationsCTE
WHERE [Type] = 1
UNION ALL
SELECT TOP 1000
[Name]
,[Building]
,CAST([Observation] AS NVARCHAR(50)) AS [PivotValue] -- Pivot value effectively combines the Observation & Observer column to help simplify the pivot query.
,[ObservationType] AS [PivotID]
,[Observation]
,1 AS [OrderRank] -- use this field to help order records.
FROM ObservationsCTE
WHERE [Type] <> 1
)
INSERT INTO #IntermResults -- Insert the results into an intermediate table.
(
[Name]
,[Building]
,[PivotValue]
,[PivotID]
,[Observation]
,[OrderRank]
)
SELECT [Name]
,[Building]
,[PivotValue]
,[PivotID]
,[Observation]
,[OrderRank]
FROM ObservationsWithPivotIDs
-- Determine what columns will be created for the pivot
SELECT @columns += N', ' + QUOTENAME([PivotID])
,@selectClause += N', ' + (CASE [OrderRank]
WHEN 1 THEN 'CAST(' + QUOTENAME([PivotID]) + ' AS DATETIME) AS ' + QUOTENAME([PivotID])
ELSE [PivotID]
END)
FROM #IntermResults
ORDER BY [Observation], [OrderRank]
-- Create dynamic query to create the pivot
SET @sql = N'
SELECT [Name], [Building], ' + STUFF(@selectClause, 1, 2, '') + '
FROM (
SELECT [Name]
,[Building]
,[PivotValue]
,[PivotID]
FROM #IntermResults
) i
PIVOT
(
MAX([PivotValue]) FOR [PivotID] IN ('
+ STUFF(@columns, 1, 1, '')
+ ')
) AS p;';
PRINT @sql;
-- Execute dynamic pivot query
EXEC sp_executesql @sql;
-- Drop intermediate results
DROP TABLE #IntermResults
有数以百计的有关SQL Server的问题在网站上摆动,有你试着看类似的帖子? – Tanner
为什么你想要的结果有名为'Interim',Summative'和'Overall'的列?这些列名背后的逻辑是什么?他们当然不是来自数据。 –