我必须在列中获得可变数量的行。我有类似的东西:
EMP EMP_ID DIV_ID ALLOCATION
Smith, Tom 3605 11300 20.00
Smith, Tom 13605 11310 80.00
Benetar, Pat 7460 11012 25.00
Benetar, Pat 7460 11015 75.00
Walkin, Chris 13892 11012 90.00
Walkin, Chris 13892 11015 10.00
Kent, Clark 12262 10015 50.00
Kent, Clark 12262 11210 25.00
Kent, Clark 12262 11220 25.00
我正在寻找的是:
EMP EMP_ID DIV_ID_01 DIV_01_ALOC DIV_ID_02 DIV_02_ALOC DIV_ID_03 DIV_03_ALOC
Smith, Tom 3605 11300 20.00 11310 80.00
Benetar, Pat 13605 11012 25.00 11015 75.00
Walkin, Chris 13892 11012 90.00 11015 10.00
Kent, Clark 12262 11015 50.00 11210 25.00 11220 25.00
我想避免使用大量的CASE语句。我现在正在尝试使用枢轴,但是在标题上遇到了困难。
答案 0 :(得分:0)
更新:
经过几次尝试后,我想出了下面的解决方案,该解决方案使用了两个GROUP BY
函数和一个with testdata(Emp, EMP_ID, DIV_ID, ALLOCATION)
as
(
select 'Smith, Tom',3605, 11300,20.00
union all
select 'Smith, Tom',3605, 11310, 80.00
union all
select 'Benetar, Pat',7460, 11012,25.00
union all
select 'Benetar, Pat',7460, 11015,75.00
union all
select 'Walkin, Chris',13892, 11012, 90.00
union all
select 'Walkin, Chris', 13892, 11015, 10.00
union all
select 'Kent, Clark', 12262, 10015, 50.00
union all
select 'Kent, Clark', 12262, 11210, 25.00
union all
select 'Kent, Clark', 12262, 11220, 25.00
)
SELECT Emp
,EMP_ID
,MAX([Div1]) AS DIV_ID_01
,MAX([Alloc1]) AS DIV_01_ALOC
,MAX([Div2]) AS DIV_ID_02
,MAX([Alloc2]) AS DIV_02_ALOC
,MAX([Div3]) AS DIV_ID_03
,MAX([Alloc3]) AS DIV_03_ALOC
FROM (
SELECT *
,cast(dense_rank() OVER (PARTITION BY emp_id
ORDER BY div_id asc) AS nvarchar) AS [emp_rnk]
,'Alloc' + cast(dense_rank() OVER (PARTITION BY emp_id
ORDER BY div_id asc) AS nvarchar) AS [piv_Alloc_rnk]
,'Div' + cast(dense_rank() OVER (PARTITION BY emp_id
ORDER BY div_id asc) AS nvarchar) AS [piv_Div_rnk]
FROM testdata td
) query
/* After both PIVOT functions are compplete, it still returns a single row for each EMP_ID.
So further aggregation is needed to 'flatten' the result. */
PIVOT (Max(Div_id) FOR [piv_Div_rnk] IN ([Div1],[Div2],[Div3])) AS pivot1
PIVOT (Max(Allocation) FOR [piv_Alloc_rnk] in([Alloc1],[Alloc2],[Alloc3])) AS pivot2
/* Since there is only one value in each of the columns created by the PIVOTS for each EMP_ID taking
the MAX() value and grouping by EMP and EMP_ID flattens the result down to the desired output. */
GROUP BY emp, emp_id
ORDER BY DIV_ID_01 DESC
来匹配您的预期结果。
以下是代码。注意:这适用于SQL Server 2005 +
EXTRA x509.UnknownAuthorityError=x509: certificate signed by unknown authority
答案 1 :(得分:0)
仅供参考,如果你试图在这里使用动态PIVOT,你最终需要一个看起来像这样的查询。
SELECT [EMP],
[EMP_ID],
MIN(DIV_ID_1) [DIV_ID_1],
SUM(DIV_1_ALOC) [DIV_1_ALOC],
MIN(DIV_ID_2) [DIV_ID_2],
SUM(DIV_2_ALOC) [DIV_2_ALOC],
MIN(DIV_ID_3) [DIV_ID_3],
SUM(DIV_3_ALOC) [DIV_3_ALOC]
FROM (SELECT [EMP],
[EMP_ID],
[DIV_ID],
[ALLOCATION],
CONCAT('DIV_ID_',DENSE_RANK () OVER (PARTITION BY [EMP] ORDER BY [DIV_ID])) ID_RN,
CONCAT('DIV_',DENSE_RANK () OVER (PARTITION BY [EMP] ORDER BY [DIV_ID]),'_ALOC') ALLOC_RN
FROM EmpTable
) t
PIVOT (
MIN([DIV_ID])
FOR ID_RN IN ([DIV_ID_1],[DIV_ID_2],[DIV_ID_3]) ) p1
PIVOT (
SUM([ALLOCATION])
FOR ALLOC_RN IN ([DIV_1_ALOC],[DIV_2_ALOC],[DIV_3_ALOC]) ) p2
GROUP BY [EMP],
[EMP_ID]
由于双轴,你需要动态创建SELECT和PIVOT列。
另一方面,如果你使用CASE语句,你只需要动态创建SELECT,因为那个查询看起来像
SELECT [EMP],
[EMP_ID],
MIN(CASE WHEN RN = 1 THEN [DIV_ID] END) [DIV_ID_1],
SUM(CASE WHEN RN = 1 THEN [ALLOCATION] END) [DIV_1_ALOC],
MIN(CASE WHEN RN = 2 THEN [DIV_ID] END) [DIV_ID_2],
SUM(CASE WHEN RN = 2 THEN [ALLOCATION] END) [DIV_2_ALOC],
MIN(CASE WHEN RN = 3 THEN [DIV_ID] END) [DIV_ID_3],
SUM(CASE WHEN RN = 3 THEN [ALLOCATION] END) [DIV_3_ALOC]
FROM (
SELECT *,
DENSE_RANK () OVER (PARTITION BY [EMP] ORDER BY [DIV_ID]) RN
FROM EmpTable
) t
GROUP BY [EMP],
[EMP_ID]
您的动态陈述看起来像
DECLARE @CaseSelect VARCHAR(MAX)
SELECT @CaseSelect = COALESCE(@CaseSelect + ',','')
+ 'MIN(CASE WHEN RN = ' + RN + ' THEN [DIV_ID] END) [DIV_ID_' + RN + '],'
+ 'SUM(CASE WHEN RN = ' + RN + ' THEN [ALLOCATION] END) [DIV_' + RN + '_ALOC]'
FROM (
SELECT DISTINCT CONVERT(VARCHAR(2),DENSE_RANK () OVER (PARTITION BY [EMP] ORDER BY [DIV_ID])) RN
FROM EmpTable
) t
ORDER BY RN
DECLARE @SQL VARCHAR(MAX)
SET @SQL = '
SELECT [EMP],
[EMP_ID], '
+ @CaseSelect + '
FROM (
SELECT *,
DENSE_RANK () OVER (PARTITION BY [EMP] ORDER BY [DIV_ID]) RN
FROM EmpTable
) t
GROUP BY [EMP], [EMP_ID]
'
EXEC(@SQL)
用您实际的表名称替换EmpTable
。