我有一个有效的动态数据透视查询,但在让我的总行显示为单行时遇到了一些麻烦。相反,它为每个技术人员提供了一个总计行,为我的总计列和发票金额列提供了一个总计行。发票列还显示了错误的总计,而总计列是正确的。
这是我当前得到的结果示例。我省略了“收费使用”,因为从它的外观来看,这都是正确的。
通话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
我从评论搬到这里。测试这样的东西
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,总记录上的连接将无法工作。