SQL Server 2005 - 动态 PIVOT 查询
SQL Server 2005 - Dynamic PIVOT query
我需要您帮助解决 PIVOT
查询问题。
场景是我有一个投票系统。由 3 个表组成。
选举、候选人、投票。
PIVOT 涉及 PIVOTing
候选人姓名作为列,并将 VOTE 数据作为数据。
到目前为止我已经尝试过这个但没有成功,我已经陷入了混乱:(
CREATE TABLE #MYELECTIONS (E_POSITION_CODE INT, E_POSITIONNAME VARCHAR(50))
INSERT INTO #MYELECTIONS VALUES (147,'MANAGER')
INSERT INTO #MYELECTIONS VALUES (148,'CHEF')
INSERT INTO #MYELECTIONS VALUES (149,'WAITER')
CREATE TABLE #MYCANDIDATES (C_CANDIDATE_CODE INT,
C_CANDIDATENAME VARCHAR (50), C_POSITION_CODE INT)
INSERT INTO #MYCANDIDATES VALUES (100,'TOM CRUISE', 147)
INSERT INTO #MYCANDIDATES VALUES (101,'MICKY MOUSE', 147)
INSERT INTO #MYCANDIDATES VALUES (103,'DONALD DUCK', 147)
INSERT INTO #MYCANDIDATES VALUES (100,'TOM CRUISE', 148)
CREATE TABLE #MYVOTES (V_POSITION_CODE INT,
V_CANDIDATE_CODE INT, VOTINGPREFERENCE SMALLINT)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,101,1)
INSERT INTO #MYVOTES VALUES (147,101,1)
INSERT INTO #MYVOTES VALUES (147,103,1)
INSERT INTO #MYVOTES VALUES (148,100,1)
INSERT INTO #MYVOTES VALUES (148,100,1)
DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)
DECLARE @MyPositionCode AS INT
SET @MyPositionCode = 147
DECLARE @MyOutput AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT @ColumnName = ISNULL(@ColumnName + ',','')
+ QUOTENAME(C_CANDIDATENAME)
FROM (SELECT TOP 100 PERCENT C_CANDIDATENAME
FROM #MYCANDIDATES
WHERE C_POSITION_CODE = @MyPositionCode
ORDER BY C_CANDIDATE_CODE) AS C_CANDIDATENAME
--Prepare the `PIVOT` query using the dynamic sql
SET @DynamicPivotQuery =
N'SELECT ROW_NUMBER() OVER (ORDER BY E_POSITIONNAME) AS Idnum,
E_POSITIONNAME AS [Position Name], ' + @ColumnName + '
FROM #MYVOTES
INNER JOIN #MYELECTIONS
ON (#MYVOTES.V_POSITION_CODE = #MYELECTIONS.E_POSITION_CODE)
PIVOT(SUM(VOTINGPREFERENCE))
FOR C_CANDIDATENAME IN (' + @ColumnName + ') AS PVTTable
WHERE #MYELECTIONS.E_POSITION_CODE = 147'
--Execute the Dynamic Pivot Query
EXEC sp_executesql @DynamicPivotQuery,
@MyOutput = @MyOutput OUTPUT
SELECT @MyOutput
DROP TABLE #MYELECTIONS
DROP TABLE #MYCANDIDATES
DROP TABLE #MYVOTES
它必须是动态的 PIVOT
,因为我想 Pivot
作为列的候选人姓名可以是动态的,具体取决于选举职位有多少候选人。
上面的期望输出是这样的:-
选@MyPositionCode = 147
Idnum Position_Name TOM CRUISE MICKY MOUSE DONALD DUCK...
1 MANAGER 4 2 1
选@MyPositionCode = 148
Idnum Position_Name TOM CRUISE MICKY MOUSE DONALD DUCK...
1 CHEF 2 0 0
试试这个
DECLARE @MyPositionCode AS INT
SET @MyPositionCode = 147
声明用于选择动态列的变量
DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)
DECLARE @cols NVARCHAR (MAX)
SELECT @cols = COALESCE (@cols + ',[' + C_CANDIDATENAME + ']', '[' + C_CANDIDATENAME + ']')
FROM
(
SELECT TOP 100 PERCENT C_CANDIDATENAME
FROM #MYCANDIDATES
WHERE C_POSITION_CODE = @MyPositionCode
ORDER BY C_CANDIDATE_CODE
) PV
ORDER BY C_CANDIDATENAME desc
如果你想用零替换NULL
DECLARE @NulltoZeroCols NVARCHAR (MAX)
SELECT @NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+C_CANDIDATENAME+'],0) AS ['+C_CANDIDATENAME+']'
FROM
(
SELECT TOP 100 PERCENT C_CANDIDATENAME
FROM #MYCANDIDATES
WHERE C_POSITION_CODE = @MyPositionCode
ORDER BY C_CANDIDATE_CODE
)TAB
ORDER BY C_CANDIDATENAME desc FOR XML PATH('')),2,8000)
现在动态旋转它。我把里面的逻辑都写好了
DECLARE @query NVARCHAR(MAX)
SET @query = '-- You can apply ROW_NUMBER() here which is the data after pivot
SELECT ROW_NUMBER() OVER (ORDER BY E_POSITIONNAME) AS Idnum,
,E_POSITIONNAME,'+@NullToZeroCols+'
FROM
(
-- Select data before pivot
SELECT TOP 100 PERCENT ME.E_POSITIONNAME,MC.C_CANDIDATENAME,
COUNT(MC.C_CANDIDATENAME) OVER(PARTITION BY ME.E_POSITIONNAME,MC.C_CANDIDATENAME) CNT
FROM #MYELECTIONS ME
JOIN #MYCANDIDATES MC ON ME.E_POSITION_CODE=MC.C_POSITION_CODE
JOIN #MYVOTES MV ON MC.C_CANDIDATE_CODE=MV.V_CANDIDATE_CODE
AND MV.V_POSITION_CODE=MC.C_POSITION_CODE
WHERE MC.C_POSITION_CODE = ' + CAST(@MyPositionCode AS VARCHAR(30)) + '
) x
PIVOT
(
MIN(CNT)
FOR C_CANDIDATENAME IN (' + @cols + ')
) p
;'
EXEC SP_EXECUTESQL @query
点击下方link。如果结果不是自动生成的,请按 运行 QUERY 按钮。
- Click here 查看结果
我需要您帮助解决 PIVOT
查询问题。
场景是我有一个投票系统。由 3 个表组成。
选举、候选人、投票。
PIVOT 涉及 PIVOTing
候选人姓名作为列,并将 VOTE 数据作为数据。
到目前为止我已经尝试过这个但没有成功,我已经陷入了混乱:(
CREATE TABLE #MYELECTIONS (E_POSITION_CODE INT, E_POSITIONNAME VARCHAR(50))
INSERT INTO #MYELECTIONS VALUES (147,'MANAGER')
INSERT INTO #MYELECTIONS VALUES (148,'CHEF')
INSERT INTO #MYELECTIONS VALUES (149,'WAITER')
CREATE TABLE #MYCANDIDATES (C_CANDIDATE_CODE INT,
C_CANDIDATENAME VARCHAR (50), C_POSITION_CODE INT)
INSERT INTO #MYCANDIDATES VALUES (100,'TOM CRUISE', 147)
INSERT INTO #MYCANDIDATES VALUES (101,'MICKY MOUSE', 147)
INSERT INTO #MYCANDIDATES VALUES (103,'DONALD DUCK', 147)
INSERT INTO #MYCANDIDATES VALUES (100,'TOM CRUISE', 148)
CREATE TABLE #MYVOTES (V_POSITION_CODE INT,
V_CANDIDATE_CODE INT, VOTINGPREFERENCE SMALLINT)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,101,1)
INSERT INTO #MYVOTES VALUES (147,101,1)
INSERT INTO #MYVOTES VALUES (147,103,1)
INSERT INTO #MYVOTES VALUES (148,100,1)
INSERT INTO #MYVOTES VALUES (148,100,1)
DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)
DECLARE @MyPositionCode AS INT
SET @MyPositionCode = 147
DECLARE @MyOutput AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT @ColumnName = ISNULL(@ColumnName + ',','')
+ QUOTENAME(C_CANDIDATENAME)
FROM (SELECT TOP 100 PERCENT C_CANDIDATENAME
FROM #MYCANDIDATES
WHERE C_POSITION_CODE = @MyPositionCode
ORDER BY C_CANDIDATE_CODE) AS C_CANDIDATENAME
--Prepare the `PIVOT` query using the dynamic sql
SET @DynamicPivotQuery =
N'SELECT ROW_NUMBER() OVER (ORDER BY E_POSITIONNAME) AS Idnum,
E_POSITIONNAME AS [Position Name], ' + @ColumnName + '
FROM #MYVOTES
INNER JOIN #MYELECTIONS
ON (#MYVOTES.V_POSITION_CODE = #MYELECTIONS.E_POSITION_CODE)
PIVOT(SUM(VOTINGPREFERENCE))
FOR C_CANDIDATENAME IN (' + @ColumnName + ') AS PVTTable
WHERE #MYELECTIONS.E_POSITION_CODE = 147'
--Execute the Dynamic Pivot Query
EXEC sp_executesql @DynamicPivotQuery,
@MyOutput = @MyOutput OUTPUT
SELECT @MyOutput
DROP TABLE #MYELECTIONS
DROP TABLE #MYCANDIDATES
DROP TABLE #MYVOTES
它必须是动态的 PIVOT
,因为我想 Pivot
作为列的候选人姓名可以是动态的,具体取决于选举职位有多少候选人。
上面的期望输出是这样的:-
选@MyPositionCode = 147
Idnum Position_Name TOM CRUISE MICKY MOUSE DONALD DUCK...
1 MANAGER 4 2 1
选@MyPositionCode = 148
Idnum Position_Name TOM CRUISE MICKY MOUSE DONALD DUCK...
1 CHEF 2 0 0
试试这个
DECLARE @MyPositionCode AS INT
SET @MyPositionCode = 147
声明用于选择动态列的变量
DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)
DECLARE @cols NVARCHAR (MAX)
SELECT @cols = COALESCE (@cols + ',[' + C_CANDIDATENAME + ']', '[' + C_CANDIDATENAME + ']')
FROM
(
SELECT TOP 100 PERCENT C_CANDIDATENAME
FROM #MYCANDIDATES
WHERE C_POSITION_CODE = @MyPositionCode
ORDER BY C_CANDIDATE_CODE
) PV
ORDER BY C_CANDIDATENAME desc
如果你想用零替换NULL
DECLARE @NulltoZeroCols NVARCHAR (MAX)
SELECT @NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+C_CANDIDATENAME+'],0) AS ['+C_CANDIDATENAME+']'
FROM
(
SELECT TOP 100 PERCENT C_CANDIDATENAME
FROM #MYCANDIDATES
WHERE C_POSITION_CODE = @MyPositionCode
ORDER BY C_CANDIDATE_CODE
)TAB
ORDER BY C_CANDIDATENAME desc FOR XML PATH('')),2,8000)
现在动态旋转它。我把里面的逻辑都写好了
DECLARE @query NVARCHAR(MAX)
SET @query = '-- You can apply ROW_NUMBER() here which is the data after pivot
SELECT ROW_NUMBER() OVER (ORDER BY E_POSITIONNAME) AS Idnum,
,E_POSITIONNAME,'+@NullToZeroCols+'
FROM
(
-- Select data before pivot
SELECT TOP 100 PERCENT ME.E_POSITIONNAME,MC.C_CANDIDATENAME,
COUNT(MC.C_CANDIDATENAME) OVER(PARTITION BY ME.E_POSITIONNAME,MC.C_CANDIDATENAME) CNT
FROM #MYELECTIONS ME
JOIN #MYCANDIDATES MC ON ME.E_POSITION_CODE=MC.C_POSITION_CODE
JOIN #MYVOTES MV ON MC.C_CANDIDATE_CODE=MV.V_CANDIDATE_CODE
AND MV.V_POSITION_CODE=MC.C_POSITION_CODE
WHERE MC.C_POSITION_CODE = ' + CAST(@MyPositionCode AS VARCHAR(30)) + '
) x
PIVOT
(
MIN(CNT)
FOR C_CANDIDATENAME IN (' + @cols + ')
) p
;'
EXEC SP_EXECUTESQL @query
点击下方link。如果结果不是自动生成的,请按 运行 QUERY 按钮。
- Click here 查看结果