在多个列上与一个连接的动态枢轴作斗争
Struggling with a dynamic pivot on multiple columns with one being concatenated
我有一个 table 数据如下:
Employee PRDate Type Code Amount Subject Eligible
1234 1/1/2015 D 1 100.00 100.00 0.00
1234 1/1/2015 D 2 200.00 0.00 0.00
5678 1/1/2015 D 1 500.00 40.00 500.00
1234 1/1/2015 E 1 300.00 30.00 300.00
5678 1/1/2015 E 1 700.00 700.00 500.00
1234 1/1/2015 E 2 400.00 200.00 0.00
1234 1/8/2015 L 55 40.00 40.00 40.00
我需要这样显示数据:
Employee PRDate D1Amt D1Subj D1Elig D2Amt D2Subj D2Elig E1Amt E1Subj E1Elig E2Amt E2Subj E2Elig L55Amt L55Subj L55Elig
1234 1/1/2015 100.00 100.00 0.00 200.00 0.00 0.00 300.00 30.00 300.00 400.00 200.00 0.00 40.00 40.00 40.00
4678 1/1/2015 500.00 40.00 500.00 700.00 700.00 500.00
我可以在一列上进行旋转,但是当我尝试组合类型和代码列以获得转换错误时(类型是 varchar,代码是 tinyint)。除了动态枢轴之外,我不确定如何获得所需的结果。能否达到预期的效果?
我已经走到这一步了,但我不知道如何组合类型、代码和每个钱列(金额、主题和合格)以获取正确列下的数据。
IF EXISTS (
SELECT *
FROM sys.tables
WHERE name LIKE '#temp285865%')
DROP TABLE #temp285865;
Create table dbo.#temp285865
(
EDLCodetemp varchar(10)
);
INSERT INTO #temp285865
(
[EDLCodetemp]
)
SELECT DISTINCT EDLCode
FROM #results
ORDER BY EDLCode;
-- Building a comma separated list of EDLCodes in #edltemp
DECLARE @cols varchar(1000);
SELECT @cols = COALESCE(@cols + ',[' + [EDLCodetemp] + ']', '[' + [EDLCodetemp] + ']')
FROM #temp285865;
-- Building the query appending columns
DECLARE @query varchar(4000);
SET @query =
'SELECT [CoName],
[PRCo],
[PRGroup],
[PREndDate],
[PaySeq],
[EDLType],
[Hours],
[SubjectAmt],
[EligibleAmt],
[PaidMth],
[LastName],
[FirstName],
[UseOver],
[OverAmt],
[Amount],
[PRGRDescrip],
[LimitPeriod],
[LimitMth],
[PREHEmployee],
[SortName],
[PaybackAmt],
[PaybackOverAmt],
[PaybackOverYN],
[PRDTEmployee],
[TrueEarns], '
+ @cols + ' FROM
(
SELECT [CoName],
[PRCo],
[PRGroup],
[PREndDate],
[PaySeq],
[EDLType],
[Hours],
[SubjectAmt],
[EligibleAmt],
[PaidMth],
[LastName],
[FirstName],
[PRDLDescrip],
[PRECDescrip],
[UseOver],
[OverAmt],
[Amount],
[PRGRDescrip],
[LimitPeriod],
[LimitMth],
[PREHEmployee],
[SortName],
[PaybackAmt],
[PaybackOverAmt],
[PaybackOverYN],
[PRDTEmployee],
[TrueEarns],
[EDLCode]
FROM #results
) p
PIVOT (
MAX(EDLCode)
FOR [EDLCode] IN (' + @cols + ')
)
as pvt';
EXEC(@query);
DROP TABLE #temp285865;
根据您提供的输入数据,以下具有动态 SQL 的 PIVOT 将为您提供所需的结果(尽管我更改了最后一行中的 PRDate)。
第一个语句构建了一个中间 table #bt
,其中包含您想要的列名和相关值。然后在 @cols
中为动态 SQL 语句构建列名。最后,中间 table #bt
使用动态 SQL 语句使用 @cols
进行透视。
SET NOCOUNT ON;
CREATE TABLE #t(
Employee INT,
PRDate DATETIME,
Type CHAR(1),
Code TINYINT,
Amount DECIMAL(28,2),
Subject DECIMAL(28,2),
Eligible DECIMAL(28,2)
);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','D',1,100.00,100.00,0.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','D',2,200.00,0.00,0.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(5678,'2015-01-01','D',1,500.00,40.00,500.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','E',1,300.00,30.00,300.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(5678,'2015-01-01','E',1,700.00,700.00,500.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','E',2,400.00,200.00,0.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','L',55,40.00,40.00,40.00);
SELECT
Employee,
PRDate,
Type+CAST(Code AS VARCHAR(3))+ca.name AS colname,
ca.val
INTO
#bt
FROM
#t
CROSS APPLY(
SELECT Amount AS val,'Amt' AS name
UNION ALL
SELECT Subject AS val,'Subj' AS name
UNION ALL
SELECT Eligible AS val,'Elig' AS name
) AS ca;
/* If you need to SUM for all dates, instead use this statement to create #bt
SELECT
Employee,
Type+CAST(Code AS VARCHAR(3))+ca.name AS colname,
ca.val
INTO
#bt
FROM
(
SELECT
Employee,
Type,
Code,
SUM(Amount) AS Amount,
SUM(Subject) AS Subject,
SUM(Eligible) AS Eligible
FROM
#t
GROUP BY
Employee,
Type,
Code
) AS t
CROSS APPLY(
SELECT Amount AS val,'Amt' AS name
UNION ALL
SELECT Subject AS val,'Subj' AS name
UNION ALL
SELECT Eligible AS val,'Elig' AS name
) AS ca;
*/
DECLARE @cols VARCHAR(8000);
SET @cols=STUFF(
(SELECT DISTINCT
',['+colname+']'
FROM
#bt
FOR XML PATH('')),
1,
1,
''
);
DECLARE @sql VARCHAR(MAX);
SET @sql='
SELECT
*
FROM
#bt
PIVOT(
MAX(val)
FOR colname IN ('+@cols+')
) AS piv
';
EXEC (@sql);
DROP TABLE #bt;
DROP TABLE #t;
结果如下:
Employee PRDate D1Amt D1Elig D1Subj D2Amt D2Elig D2Subj E1Amt E1Elig E1Subj E2Amt E2Elig E2Subj L55Amt L55Elig L55Subj
1234 2015-01-01 100.00 0.00 100.00 200.00 0.00 0.00 300.00 300.00 30.00 400.00 0.00 200.00 40.00 40.00 40.00
5678 2015-01-01 500.00 500.00 40.00 NULL NULL NULL 700.00 500.00 700.00 NULL NULL NULL NULL NULL NULL
我有一个 table 数据如下:
Employee PRDate Type Code Amount Subject Eligible
1234 1/1/2015 D 1 100.00 100.00 0.00
1234 1/1/2015 D 2 200.00 0.00 0.00
5678 1/1/2015 D 1 500.00 40.00 500.00
1234 1/1/2015 E 1 300.00 30.00 300.00
5678 1/1/2015 E 1 700.00 700.00 500.00
1234 1/1/2015 E 2 400.00 200.00 0.00
1234 1/8/2015 L 55 40.00 40.00 40.00
我需要这样显示数据:
Employee PRDate D1Amt D1Subj D1Elig D2Amt D2Subj D2Elig E1Amt E1Subj E1Elig E2Amt E2Subj E2Elig L55Amt L55Subj L55Elig
1234 1/1/2015 100.00 100.00 0.00 200.00 0.00 0.00 300.00 30.00 300.00 400.00 200.00 0.00 40.00 40.00 40.00
4678 1/1/2015 500.00 40.00 500.00 700.00 700.00 500.00
我可以在一列上进行旋转,但是当我尝试组合类型和代码列以获得转换错误时(类型是 varchar,代码是 tinyint)。除了动态枢轴之外,我不确定如何获得所需的结果。能否达到预期的效果?
我已经走到这一步了,但我不知道如何组合类型、代码和每个钱列(金额、主题和合格)以获取正确列下的数据。
IF EXISTS (
SELECT *
FROM sys.tables
WHERE name LIKE '#temp285865%')
DROP TABLE #temp285865;
Create table dbo.#temp285865
(
EDLCodetemp varchar(10)
);
INSERT INTO #temp285865
(
[EDLCodetemp]
)
SELECT DISTINCT EDLCode
FROM #results
ORDER BY EDLCode;
-- Building a comma separated list of EDLCodes in #edltemp
DECLARE @cols varchar(1000);
SELECT @cols = COALESCE(@cols + ',[' + [EDLCodetemp] + ']', '[' + [EDLCodetemp] + ']')
FROM #temp285865;
-- Building the query appending columns
DECLARE @query varchar(4000);
SET @query =
'SELECT [CoName],
[PRCo],
[PRGroup],
[PREndDate],
[PaySeq],
[EDLType],
[Hours],
[SubjectAmt],
[EligibleAmt],
[PaidMth],
[LastName],
[FirstName],
[UseOver],
[OverAmt],
[Amount],
[PRGRDescrip],
[LimitPeriod],
[LimitMth],
[PREHEmployee],
[SortName],
[PaybackAmt],
[PaybackOverAmt],
[PaybackOverYN],
[PRDTEmployee],
[TrueEarns], '
+ @cols + ' FROM
(
SELECT [CoName],
[PRCo],
[PRGroup],
[PREndDate],
[PaySeq],
[EDLType],
[Hours],
[SubjectAmt],
[EligibleAmt],
[PaidMth],
[LastName],
[FirstName],
[PRDLDescrip],
[PRECDescrip],
[UseOver],
[OverAmt],
[Amount],
[PRGRDescrip],
[LimitPeriod],
[LimitMth],
[PREHEmployee],
[SortName],
[PaybackAmt],
[PaybackOverAmt],
[PaybackOverYN],
[PRDTEmployee],
[TrueEarns],
[EDLCode]
FROM #results
) p
PIVOT (
MAX(EDLCode)
FOR [EDLCode] IN (' + @cols + ')
)
as pvt';
EXEC(@query);
DROP TABLE #temp285865;
根据您提供的输入数据,以下具有动态 SQL 的 PIVOT 将为您提供所需的结果(尽管我更改了最后一行中的 PRDate)。
第一个语句构建了一个中间 table #bt
,其中包含您想要的列名和相关值。然后在 @cols
中为动态 SQL 语句构建列名。最后,中间 table #bt
使用动态 SQL 语句使用 @cols
进行透视。
SET NOCOUNT ON;
CREATE TABLE #t(
Employee INT,
PRDate DATETIME,
Type CHAR(1),
Code TINYINT,
Amount DECIMAL(28,2),
Subject DECIMAL(28,2),
Eligible DECIMAL(28,2)
);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','D',1,100.00,100.00,0.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','D',2,200.00,0.00,0.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(5678,'2015-01-01','D',1,500.00,40.00,500.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','E',1,300.00,30.00,300.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(5678,'2015-01-01','E',1,700.00,700.00,500.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','E',2,400.00,200.00,0.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','L',55,40.00,40.00,40.00);
SELECT
Employee,
PRDate,
Type+CAST(Code AS VARCHAR(3))+ca.name AS colname,
ca.val
INTO
#bt
FROM
#t
CROSS APPLY(
SELECT Amount AS val,'Amt' AS name
UNION ALL
SELECT Subject AS val,'Subj' AS name
UNION ALL
SELECT Eligible AS val,'Elig' AS name
) AS ca;
/* If you need to SUM for all dates, instead use this statement to create #bt
SELECT
Employee,
Type+CAST(Code AS VARCHAR(3))+ca.name AS colname,
ca.val
INTO
#bt
FROM
(
SELECT
Employee,
Type,
Code,
SUM(Amount) AS Amount,
SUM(Subject) AS Subject,
SUM(Eligible) AS Eligible
FROM
#t
GROUP BY
Employee,
Type,
Code
) AS t
CROSS APPLY(
SELECT Amount AS val,'Amt' AS name
UNION ALL
SELECT Subject AS val,'Subj' AS name
UNION ALL
SELECT Eligible AS val,'Elig' AS name
) AS ca;
*/
DECLARE @cols VARCHAR(8000);
SET @cols=STUFF(
(SELECT DISTINCT
',['+colname+']'
FROM
#bt
FOR XML PATH('')),
1,
1,
''
);
DECLARE @sql VARCHAR(MAX);
SET @sql='
SELECT
*
FROM
#bt
PIVOT(
MAX(val)
FOR colname IN ('+@cols+')
) AS piv
';
EXEC (@sql);
DROP TABLE #bt;
DROP TABLE #t;
结果如下:
Employee PRDate D1Amt D1Elig D1Subj D2Amt D2Elig D2Subj E1Amt E1Elig E1Subj E2Amt E2Elig E2Subj L55Amt L55Elig L55Subj
1234 2015-01-01 100.00 0.00 100.00 200.00 0.00 0.00 300.00 300.00 30.00 400.00 0.00 200.00 40.00 40.00 40.00
5678 2015-01-01 500.00 500.00 40.00 NULL NULL NULL 700.00 500.00 700.00 NULL NULL NULL NULL NULL NULL