在动态数据透视查询中将总行分组为一行

问题描述 投票:0回答:1

我有一个有效的动态数据透视查询,但在让我的总行显示为单行时遇到了一些麻烦。相反,它为每个技术人员提供了一个总计行,为我的总计列和发票金额列提供了一个总计行。发票列还显示了错误的总计,而总计列是正确的。

这是我当前得到的结果示例。我省略了“收费使用”,因为从它的外观来看,这都是正确的。

通话ID 开始日期 客户先生姓名 科技1 科技2 科技3 科技4 科技5 总计 已开发票 收费使用
总计 1.6
总计
总计 2.2
总计 1.46
总计 4.55
总计 2.77
总计 12.58 28
123 1.12.23 客户1 0.65 0.34 0.99 1
234 1.12.23 客户2 1.10 1.10 2
456 1.12.23 客户3 1.12 1.12 2
567 1.12.23 客户4 0.67 0.67 1
678 1.12.23 客户5 0.50 1.64 2.14 2
789 1.12.23 客户6 4.55 4.55 5
890 1.12.23 客户7 0.88 1.13 2.01 2

我想要得到的是这个。

通话ID 开始日期 客户先生姓名 科技1 科技2 科技3 科技4 科技5 总计 已开发票 收费使用
123 1.12.23 客户1 0.65 0.34 0.99 1
234 1.12.23 客户2 1.10 1.10 2
456 1.12.23 客户3 1.12 1.12 2
567 1.12.23 客户4 0.67 0.67 1
678 1.12.23 客户5 0.50 1.64 2.14 2
789 1.12.23 客户6 4.55 4.55 5
890 1.12.23 客户7 0.88 1.13 2.01 2
总计 2.2 1.6 1.46 4.55 2.77 12.58 15

这是查询的代码,它很长,所以我删除了一些与计算技术人员时间和发票金额相关的部分。

DECLARE @FRDATE DATE = /* SELECT FROM OINV T0 WHERE T0.DocDate >= */  [%0];
DECLARE @TODATE DATE = /* SELECT FROM OINV T0 WHERE T0.DocDate <= */  [%1];
DECLARE @columns NVARCHAR(MAX);
DECLARE @sql NVARCHAR(MAX);

SELECT @columns = STUFF((SELECT DISTINCT ',' + QUOTENAME(CONCAT(firstName, ' ', lastName)) [Technician]
                         FROM SCL6
                                  INNER JOIN OHEM ON SCL6.Technician = OHEM.empID
                                  INNER JOIN HEM6 ON HEM6.[empID] = OHEM.[empID]
                                  INNER JOIN HTM1 ON HTM1.[empID] = OHEM.[empID]
                         WHERE HEM6.roleID = -2 AND HTM1.teamID IN (1, 2) AND OHEM.Active = 'Y'
                         FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
                         , 1, 1, '');

DECLARE @techTime NVARCHAR(MAX);
SET @techTime = ' /* section of code for calculating tech time';

DECLARE @invoiceQuantity NVARCHAR(MAX);
SET @invoiceQuantity = ' /* section of code for calculating amount invoiced ';

SELECT @sql = '
;WITH CTE AS (
    SELECT T0.callID,
           T4.StartDate,
           T0.custMrName,
           CONCAT(OHEM.firstName, '' '', OHEM.lastName) AS Tech,
           ' + @techTime + ' AS Dur,
           B.Invoiced
    FROM OSCL T0
             INNER JOIN SCL6 T4 ON T0.callID = T4.SrcvCallID
             INNER JOIN OHEM ON T4.Technician = OHEM.empID
             INNER JOIN HEM6 ON HEM6.[empID] = OHEM.[empID]
             INNER JOIN HTM1 ON HTM1.[empID] = OHEM.[empID]
             ' + @invoiceQuantity + '
    WHERE T4.[Close] = ''Y'' AND
          T4.Technician <> 104 AND
          HEM6.roleID = -2 AND
          HTM1.teamID IN (1, 2) AND
          T0.customer <> ''C003435'' AND
          T4.StartDate BETWEEN @FRDATE AND @TODATE
    GROUP BY T0.callID, T4.StartDate, OHEM.firstName, OHEM.lastName, T4.Technician, T4.StartTime, T4.EndDate, T4.ChkInTime, T4.ChkOutTime, T4.EndTime, T4.ChkInDate, T4.ChkOutDate, B.Invoiced, T0.custMrName
    UNION ALL
    SELECT T0.callID,
           T4.StartDate,
           T0.custMrName,
           ''Total'' AS ''Total'',
           ' + @techTime + ' AS Dur,
           B.Invoiced
    FROM OSCL T0
             INNER JOIN SCL6 T4 ON T0.callID = T4.SrcvCallID
             INNER JOIN OHEM ON T4.Technician = OHEM.empID
             INNER JOIN HEM6 ON HEM6.[empID] = OHEM.[empID]
             INNER JOIN HTM1 ON HTM1.[empID] = OHEM.[empID]
             ' + @invoiceQuantity + '
          WHERE T4.[Close] = ''Y'' AND
          T4.Technician <> 104 AND
          HEM6.roleID = -2 AND
          HTM1.teamID IN (1, 2) AND
          T0.customer <> ''C003435'' AND
          T4.StartDate BETWEEN @FRDATE AND @TODATE
    GROUP BY T0.callID, T4.StartDate, T4.Technician, OHEM.firstName, OHEM.lastName, T4.StartTime, T4.EndDate, T4.ChkInTime, T4.ChkOutTime, T4.EndTime, T4.ChkInDate, T4.ChkOutDate, B.Invoiced, T0.custMrName
)

SELECT p.callID,
       p.StartDate,
       p.custMrName,
       ' + @columns + ',
       Total,
       Invoiced,
CASE WHEN ISNULL(Invoiced, 0) = 0 THEN NULL ELSE CAST(CAST(ROUND(Invoiced / NULLIF(Total, 0) * 100,0) AS INT) AS VARCHAR) + ''%'' END AS [Chargeable Utilization]
FROM (
SELECT callID, StartDate, custMrName, Tech, Dur, Invoiced FROM CTE
UNION ALL
SELECT 
        NULL AS callID, 
        NULL AS StartDate, 
        ''Total'' AS custMrName, 
        Tech,
        SUM(Dur) AS Dur, 
        SUM(Invoiced) AS Invoiced 
    FROM CTE
    GROUP BY Tech
) AS t
         PIVOT (SUM(Dur) FOR Tech IN (' + @columns + ',Total)) p
ORDER BY p.StartDate ASC';

EXEC sp_executesql @sql, N'@FRDATE DATE, @TODATE DATE', @FRDATE, @TODATE
sql pivot dynamic-sql sapb1
1个回答
0
投票

我从评论搬到这里。测试这样的东西

with CTE as (...)

,CTE_a as (SELECT p.callID,
       p.StartDate,
       p.custMrName,
       ' + @columns + ',
       Total

FROM (
SELECT callID, StartDate, custMrName, Tech, Dur FROM CTE
UNION ALL
SELECT 
        NULL AS callID, 
        NULL AS StartDate, 
        ''Total'' AS custMrName, 
        Tech,
        SUM(Dur) AS Dur--, 
        --SUM(Invoiced) AS Invoiced 
    FROM CTE
    GROUP BY Tech
) AS t
         PIVOT (SUM(Dur) FOR Tech IN (' + @columns + ',Total)) p
ORDER BY p.StartDate ASC)

,CTE_b as (SELECT callID, StartDate, custMrName, sum(Invoiced) as Invoiced FROM CTE group by callID, StartDate, custMrName
UNION ALL
SELECT 
        NULL AS callID, 
        NULL AS StartDate, 
        ''Total'' AS custMrName, 
        SUM(Invoiced) AS Invoiced 
    FROM CTE
    )

select a.*,b.invoiced
,CASE WHEN ISNULL(b.Invoiced, 0) = 0 THEN NULL ELSE CAST(CAST(ROUND(b.Invoiced / NULLIF(a.Total, 0) * 100,0) AS INT) AS VARCHAR) + ''%'' END AS [Chargeable Utilization]
    from CTE_a a
    inner join CTE_b b
    on isnull(a.callID,0)=isnull(b.callID,0)
    and isnull(a.StartDate,'99991231') =isnull(b.StartDate,'99991231')
    and a.custMrName=b.custMrName

最后一部分在连接中使用 CallID 和 StartDate 时要注意。在“总计”记录中,您需要管理一些空值:如果 CallId 是正整数,我认为 isnull(..,0) 是一个很好的解决方案;关于 StartDate 我建议“99991231”,但重要的是选择一个“假”值,这样您就可以在 StartDate 上观察到超出实际值范围的值。否则我认为如果没有这些 isnulls,总记录上的连接将无法工作。

© www.soinside.com 2019 - 2024. All rights reserved.