在 SQL 服务器中使用 pivot 动态构建静态列
Dynamically construct static columns using pivot in SQL Server
我有一个不包含这些列(Visit_date、M-1、M-2、M-3)的主 table,但最终我需要这些列(Visit_date、M-1、M-2、M-3) 以及现有的主 table 列,例如
Retailer_id, survey_id, Group_Id, survery_Name
我尝试使用 pivot 但无法完成最终结果,请提供一些示例
硕士table:
RetailerID Retailer SurveyName Date Score Weights
198760 ABC Quality 06/03/2016 10 10
198760 ABC Quality 06/02/2016 5 10
198760 ABC Quality 06/01/2016 5 5
198760 ABC Quality 06/12/2015 10 10
预期结果:
Retailer_id survery_Name Last_Visit M-1 M-2 M-3 Weightage
198760 quality 10 5 5 10 10
脚本:
CREATE TABLE [dbo].[Master_Table]
(
[Retailer_ID] [nvarchar](50) NULL,
[RQSC_Survey_Name] [nvarchar](50) NULL,
[RQSC_Date] [date] NULL,
[RQSC_Weightage] [decimal](18, 0) NULL,
[RQSC_Score] [decimal](18, 0) NULL
) ON [PRIMARY]
INSERT [dbo].[Master_Table] ([Retailer_ID], [RQSC_Survey_Name], [RQSC_Date], [RQSC_Weightage], [RQSC_Score])
VALUES (N'198760', N'Quality', CAST(0x1C3B0B00 AS Date), CAST(10 AS Decimal(18, 0)), CAST(10 AS Decimal(18, 0)))
INSERT [dbo].[Master_Table] ([Retailer_ID], [RQSC_Survey_Name], [RQSC_Date], [RQSC_Weightage], [RQSC_Score])
VALUES (N'198760', N'Quality', CAST(0x003B0B00 AS Date), CAST(10 AS Decimal(18, 0)), CAST(5 AS Decimal(18, 0)))
INSERT [dbo].[Master_Table] ([Retailer_ID], [RQSC_Survey_Name], [RQSC_Date], [RQSC_Weightage], [RQSC_Score])
VALUES (N'198760', N'Quality', CAST(0xE13A0B00 AS Date), CAST(5 AS Decimal(18, 0)), CAST(5 AS Decimal(18, 0)))
INSERT [dbo].[Master_Table] ([Retailer_ID], [RQSC_Survey_Name], [RQSC_Date], [RQSC_Weightage], [RQSC_Score])
VALUES (N'198760', N'Quality', CAST(0xC23A0B00 AS Date), CAST(10 AS Decimal(18, 0)), CAST(10 AS Decimal(18, 0)))
我的查询:
SELECT
Retailer_ID, RQSC_Survey_Name,
[1] As LastVist, [2] as 'M-1', [3] as 'M-2', [4] as 'M-3',
[1] as 'Score'
FROM
(SELECT
RQSC_Score, Retailer_ID, RQSC_Survey_Name,
RQSC_Weightage,
ROW_NUMBER() OVER (PARTITION BY Retailer_ID ORDER BY RQSC_Date DESC) AS Rownumber
FROM
master_table
WHERE
Retailer_ID = 198760 AND RQSC_Survey_Id = 298) src
PIVOT(SUM(RQSC_Score)for Rownumber in ([1], [2], [3],[4])) piv;
在这里,如果我 select 权重列,我将根据权重列获得重复的行,但在预期结果中我应该获得权重列
抱歉工作耽搁了。根据您的示例数据,我们可以实现使用 Stuff 和 Dynamic Sql
IF object_id('tempdb..#Temp') is not null
DROP TABLE #TEMP
CREATE TABLE #Temp
(Retailer varchar(10), SurveyName varchar(10), Date datetime, Score int, Weights int)
;
INSERT INTO #Temp
(Retailer, SurveyName, Date, Score, Weights)
VALUES
('198760', 'Quality', '2016-06-03 05:30:00', 10, 10),
('198760', 'Quality', '2016-06-02 05:30:00', 5, 10),
('198760', 'Quality', '2016-06-01 05:30:00', 5, 5),
('198760', 'Quality', '2015-06-12 05:30:00', 10, 10)
;
DECLARE @statement NVARCHAR(max)
,@columns NVARCHAR(max),
@col NVARCHAR(max)
SELECT @columns =
STUFF((SELECT distinct '],[' +
CAST(ROW_NUMBER() OVER (PARTITION BY Retailer ORDER BY Date DESC) AS VARCHAR(50)) AS Rownumber
FROM #Temp
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 2, '')+ ']'
SELECT @statement = 'SELECT
Retailer, SurveyName,
MAX([1]) As LastVist, MAX([2]) as ''M-1'', MAX([3]) as ''M-2'', MAX([4]) as ''M-3'',
MAX([1]) as ''Score''
FROM
(
SELECT
Retailer, SurveyName, Score,
Weights,
ROW_NUMBER() OVER (PARTITION BY Retailer ORDER BY Date DESC) AS Rownumber
FROM
#Temp
) src
PIVOT(SUM(Score)for Rownumber in (' + @columns + ')) as pvt
GROUP BY Retailer, SurveyName'
EXEC sp_executesql @statement = @statement
我得到了解决方案
WITH CTE as
(
select retailer ,surveyname ,max([date])
over(partition by retailer,surveyname)as [date],score ,weights,
row_number() over(partition by retailer,surveyname order by [date] desc
)
as rn from #temp)
select p.retailer,p.surveyname,p.[1] as lastvisit,p.[2] as [m-1],
p.[3] as [m-2],p.[4] as [m-3],b.score,b.weights ,b.[date] from
(
select retailer,surveyname,score,rn from cte) as a pivot (sum(score)
for rn in ([1],[2],[3],[4])
) as p
inner join cte as b on b.retailer=p.retailer and b.surveyname=p.surveyname and b.rn=1 ;
我有一个不包含这些列(Visit_date、M-1、M-2、M-3)的主 table,但最终我需要这些列(Visit_date、M-1、M-2、M-3) 以及现有的主 table 列,例如
Retailer_id, survey_id, Group_Id, survery_Name
我尝试使用 pivot 但无法完成最终结果,请提供一些示例
硕士table:
RetailerID Retailer SurveyName Date Score Weights
198760 ABC Quality 06/03/2016 10 10
198760 ABC Quality 06/02/2016 5 10
198760 ABC Quality 06/01/2016 5 5
198760 ABC Quality 06/12/2015 10 10
预期结果:
Retailer_id survery_Name Last_Visit M-1 M-2 M-3 Weightage
198760 quality 10 5 5 10 10
脚本:
CREATE TABLE [dbo].[Master_Table]
(
[Retailer_ID] [nvarchar](50) NULL,
[RQSC_Survey_Name] [nvarchar](50) NULL,
[RQSC_Date] [date] NULL,
[RQSC_Weightage] [decimal](18, 0) NULL,
[RQSC_Score] [decimal](18, 0) NULL
) ON [PRIMARY]
INSERT [dbo].[Master_Table] ([Retailer_ID], [RQSC_Survey_Name], [RQSC_Date], [RQSC_Weightage], [RQSC_Score])
VALUES (N'198760', N'Quality', CAST(0x1C3B0B00 AS Date), CAST(10 AS Decimal(18, 0)), CAST(10 AS Decimal(18, 0)))
INSERT [dbo].[Master_Table] ([Retailer_ID], [RQSC_Survey_Name], [RQSC_Date], [RQSC_Weightage], [RQSC_Score])
VALUES (N'198760', N'Quality', CAST(0x003B0B00 AS Date), CAST(10 AS Decimal(18, 0)), CAST(5 AS Decimal(18, 0)))
INSERT [dbo].[Master_Table] ([Retailer_ID], [RQSC_Survey_Name], [RQSC_Date], [RQSC_Weightage], [RQSC_Score])
VALUES (N'198760', N'Quality', CAST(0xE13A0B00 AS Date), CAST(5 AS Decimal(18, 0)), CAST(5 AS Decimal(18, 0)))
INSERT [dbo].[Master_Table] ([Retailer_ID], [RQSC_Survey_Name], [RQSC_Date], [RQSC_Weightage], [RQSC_Score])
VALUES (N'198760', N'Quality', CAST(0xC23A0B00 AS Date), CAST(10 AS Decimal(18, 0)), CAST(10 AS Decimal(18, 0)))
我的查询:
SELECT
Retailer_ID, RQSC_Survey_Name,
[1] As LastVist, [2] as 'M-1', [3] as 'M-2', [4] as 'M-3',
[1] as 'Score'
FROM
(SELECT
RQSC_Score, Retailer_ID, RQSC_Survey_Name,
RQSC_Weightage,
ROW_NUMBER() OVER (PARTITION BY Retailer_ID ORDER BY RQSC_Date DESC) AS Rownumber
FROM
master_table
WHERE
Retailer_ID = 198760 AND RQSC_Survey_Id = 298) src
PIVOT(SUM(RQSC_Score)for Rownumber in ([1], [2], [3],[4])) piv;
在这里,如果我 select 权重列,我将根据权重列获得重复的行,但在预期结果中我应该获得权重列
抱歉工作耽搁了。根据您的示例数据,我们可以实现使用 Stuff 和 Dynamic Sql
IF object_id('tempdb..#Temp') is not null
DROP TABLE #TEMP
CREATE TABLE #Temp
(Retailer varchar(10), SurveyName varchar(10), Date datetime, Score int, Weights int)
;
INSERT INTO #Temp
(Retailer, SurveyName, Date, Score, Weights)
VALUES
('198760', 'Quality', '2016-06-03 05:30:00', 10, 10),
('198760', 'Quality', '2016-06-02 05:30:00', 5, 10),
('198760', 'Quality', '2016-06-01 05:30:00', 5, 5),
('198760', 'Quality', '2015-06-12 05:30:00', 10, 10)
;
DECLARE @statement NVARCHAR(max)
,@columns NVARCHAR(max),
@col NVARCHAR(max)
SELECT @columns =
STUFF((SELECT distinct '],[' +
CAST(ROW_NUMBER() OVER (PARTITION BY Retailer ORDER BY Date DESC) AS VARCHAR(50)) AS Rownumber
FROM #Temp
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 2, '')+ ']'
SELECT @statement = 'SELECT
Retailer, SurveyName,
MAX([1]) As LastVist, MAX([2]) as ''M-1'', MAX([3]) as ''M-2'', MAX([4]) as ''M-3'',
MAX([1]) as ''Score''
FROM
(
SELECT
Retailer, SurveyName, Score,
Weights,
ROW_NUMBER() OVER (PARTITION BY Retailer ORDER BY Date DESC) AS Rownumber
FROM
#Temp
) src
PIVOT(SUM(Score)for Rownumber in (' + @columns + ')) as pvt
GROUP BY Retailer, SurveyName'
EXEC sp_executesql @statement = @statement
我得到了解决方案
WITH CTE as
(
select retailer ,surveyname ,max([date])
over(partition by retailer,surveyname)as [date],score ,weights,
row_number() over(partition by retailer,surveyname order by [date] desc
)
as rn from #temp)
select p.retailer,p.surveyname,p.[1] as lastvisit,p.[2] as [m-1],
p.[3] as [m-2],p.[4] as [m-3],b.score,b.weights ,b.[date] from
(
select retailer,surveyname,score,rn from cte) as a pivot (sum(score)
for rn in ([1],[2],[3],[4])
) as p
inner join cte as b on b.retailer=p.retailer and b.surveyname=p.surveyname and b.rn=1 ;