在多个列上与一个连接的动态枢轴作斗争

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