【问题标题】:SQl calculate percentage avoid Div/0 error in Stored procedureSQl 计算百分比避免存储过程中的 Div/0 错误
【发布时间】:2020-12-10 00:27:38
【问题描述】:

我正在尝试更新一些旧的存储过程,它们目前是否有效。

它从多个表格中提取数据,为基于表格的报告创建记录集。

我遇到的问题是利用率数字,这些是百分比,但它们经常遇到除以零错误。

这是当前脚本。

CREATE PROC [PPA].[MonthlyUtilisation]

--EXEC [PPA].[MonthlyUtilisationIndividual] @Year = 1920, @Employee = 7238734, @Month = 5, @Area = 'National', @Team = 'SET'

@Year int,
@Employee int,
@Month int,
@Area varchar(55),
@Team varchar(55)

AS

DECLARE @MonthID int = (SELECT DISTINCT CONCAT([ReportYear],[ReportMonth]) FROM [PPA].[Weeks] WHERE [ReportYear] = @Year AND [ReportMonth] = @Month)

SELECT 
Ep.[EmployeePID] AS [Staff PID]
,E.[FirstName] AS [First Name]
,E.[LastName] AS [Last Name]
,G.[GradeName] AS [Staff Grade]
,Tms.[TeamName] As [Team]
,Count(Ep.[EmployeePID]) AS [*]
,Sum([WeeklyContractedHours]) AS [GROSS Available Resource]
,Isnull(Sum(f.mins), 0) AS [Planned Flexi]
,Isnull(Sum(af.mins), 0) AS [Actual Flexi]
,Isnull(Sum(l.mins), 0) AS [Planned Leave]
,Isnull(Sum(al.mins), 0) AS [Actual Leave]

,Sum([WeeklyContractedHours] 
+ Isnull(f.mins, 0) 
- Isnull(l.mins, 0))
AS [Planned NET Available Resource]

,Sum([WeeklyContractedHours] 
+ Isnull(af.mins, 0) 
- Isnull(al.mins, 0))
AS [Actual NET Available Resource]

,Isnull(Sum(i.mins), 0) AS [Planned Indirects]
,Isnull(Sum(ai.mins), 0) AS [Actual Indirects]

,Sum([WeeklyContractedHours]
+ Isnull(f.mins, 0)
- Isnull(l.mins, 0))
- Isnull(Sum(i.mins), 0)
AS [Planned GROSS Direct Resource]

,Sum([WeeklyContractedHours]
+ Isnull(af.mins, 0)
- Isnull(al.mins, 0))
- Isnull(Sum(ai.mins), 0)
AS [Actual GROSS Direct Resource]

,Round(Cast(Sum([WeeklyContractedHours]
+ Isnull(f.mins, 0) 
- Isnull(l.mins, 0)) 
- Isnull(Sum(i.mins), 0) AS FLOAT) 
/ Cast(Sum([WeeklyContractedHours] 
+ Isnull(f.mins, 0) 
- Isnull(l.mins, 0)) AS FLOAT) 
* 100, 0)
AS [Planned Utilisation]
 
,Round(Cast(Sum([WeeklyContractedHours] 
+ Isnull(af.mins, 0) 
- Isnull(al.mins, 0)) 
- Isnull(Sum(ai.mins), 0) AS FLOAT) 
/ Cast(Sum([WeeklyContractedHours] 
+ Isnull(af.mins, 0) 
- Isnull(al.mins, 0)) AS FLOAT) 
* 100, 0)
AS [Actual Utilisation]
  
FROM [PPA].[EmployeeProfiles] AS Ep 
/*=====================================
======================================*/

LEFT JOIN [PPA].[Timesheets] as Ts on Ts.[EmployeeProfileID] = Ep.[EmployeeProfileID]
LEFT JOIN [PPA].[employees] AS E ON Ep.[EmployeePID] = E.[EmployeePID] 
JOIN [PPA].[grades] AS G ON Ep.[GradeID] = G.[GradeID]
JOIN [PPA].[teams] as Tms ON Ep.[TeamID] = Tms.[TeamID]
JOIN [PPA].[areas] as A ON Tms.[AreaID] = A.[AreaID]
JOIN [PPA].[Weeks] as Wk on Ts.[WeekID] = wk.[WeekID]

--Planned Flexi Leave
LEFT JOIN (SELECT T.[TimesheetID],
Isnull(Sum(mins), 0) AS Mins 
FROM [PPA].[Stage1Leave] AS S1L 
JOIN [PPA].[timesheets] AS T ON S1L.[TimesheetID] = T.[TimesheetID]
JOIN [PPA].[Weeks] as Wk ON T.[WeekID] = wk.[WeekID]
WHERE  LeaveID = 10
AND Wk.[ReportYear]= @Year and Wk.[ReportMonth] = @Month
GROUP  BY T.[TimesheetID]) AS f 
ON f.[TimesheetID] = Ts.[TimesheetID]

--Actual Flexi Leave
LEFT JOIN (SELECT T.[TimesheetID],
Isnull(Sum(mins), 0) AS Mins 
FROM [PPA].[Stage3Leave] AS S3L 
JOIN [PPA].[timesheets] AS T ON S3L.[TimesheetID] = T.[TimesheetID]
JOIN [PPA].[Weeks] as Wk ON T.[WeekID] = wk.[WeekID]
WHERE  LeaveID = 10
AND Wk.[ReportYear]= @Year and Wk.[ReportMonth] = @Month
GROUP  BY T.[TimesheetID]) AS af 
ON af.[TimesheetID] = Ts.[TimesheetID]

--Planned Leave
LEFT JOIN (SELECT T.[TimesheetID],
Isnull(Sum(mins), 0) AS Mins 
FROM  [PPA].[Stage1Leave] AS S1L
JOIN [PPA].[timesheets] AS T ON S1L.[TimesheetID] = T.[TimesheetID]
JOIN [PPA].[Weeks] as Wk on T.[WeekID] = wk.[WeekID]
WHERE  LeaveID NOT IN (10, 12)
AND Wk.[ReportYear]= @Year and Wk.[ReportMonth] = @Month 
GROUP  BY T.[TimesheetID]) AS l 
ON l.[TimesheetID] = Ts.[TimesheetID] 

--Actual Leave
LEFT JOIN (SELECT T.[TimesheetID], 
Isnull(Sum(mins), 0) AS Mins 
FROM   [PPA].[Stage3Leave] AS S3L 
JOIN [PPA].[timesheets] AS T ON S3L.[TimesheetID] = T.[TimesheetID]
JOIN [PPA].[Weeks] as Wk on T.[WeekID] = wk.[WeekID]
WHERE  LeaveID <> 10
AND Wk.[ReportYear]= @Year and Wk.[ReportMonth] = @Month
GROUP  BY T.[TimesheetID]) AS al 
ON al.[TimesheetID] = Ts.[TimesheetID] 

--Planned Indirects
LEFT JOIN (SELECT T.[TimesheetID], 
Isnull(Sum(mins), 0) AS Mins 
FROM   [PPA].[stage1] AS S 
JOIN [PPA].[timesheets] AS T ON S.[TimesheetID] = T.[TimesheetID]
JOIN [PPA].[Weeks] as Wk on T.[WeekID] = wk.[WeekID]
WHERE Wk.[ReportYear]= @Year and Wk.[ReportMonth] = @Month
GROUP  BY T.[TimesheetID]) AS i 
ON i.[TimesheetID] = Ts.[TimesheetID]

--Actual Indirects
LEFT JOIN (SELECT T.[TimesheetID], 
Isnull(Sum(mins), 0) AS Mins 
FROM   [PPA].[stage3indirects] AS s3i
JOIN [PPA].[timesheets] AS T ON s3i.[TimesheetID] = T.[TimesheetID]
JOIN [PPA].[Weeks] as Wk on T.[WeekID] = wk.[WeekID]
WHERE Wk.[ReportYear]= @Year and Wk.[ReportMonth] = @Month
GROUP  BY T.[TimesheetID]) AS ai 
ON ai.[TimesheetID] = Ts.[TimesheetID]

WHERE Ts.[EmployeePID] = CASE WHEN @Employee = 0 THEN Ts.[EmployeePID] ELSE @Employee END
AND Tms.[TeamName] = CASE WHEN @Team = 'All' THEN [TeamName] ELSE @Team END
--AND (SELECT CONCAT([ReportYear],[ReportMonth])) = @MonthID
AND Wk.[ReportYear]= @Year and Wk.[ReportMonth] = @Month
and Ep.[Live] = 1
GROUP  BY Tms.[TeamName]
,G.[GradeName] 
,G.[GradeID]
,E.[LastName]
,E.[FirstName] 
,Ep.[EmployeePID]
ORDER  BY Tms.[TeamName], G.[GradeID]

GO

这是我正在努力解决的脚本部分

,Round(Cast(Sum([WeeklyContractedHours]
+ Isnull(f.mins, 0) 
- Isnull(l.mins, 0)) 
- Isnull(Sum(i.mins), 0) AS FLOAT) 
/ Cast(Sum([WeeklyContractedHours] 
+ Isnull(f.mins, 0) 
- Isnull(l.mins, 0)) AS FLOAT) 
* 100, 0)
AS [Planned Utilisation]
 
,Round(Cast(Sum([WeeklyContractedHours] 
+ Isnull(af.mins, 0) 
- Isnull(al.mins, 0)) 
- Isnull(Sum(ai.mins), 0) AS FLOAT) 
/ Cast(Sum([WeeklyContractedHours] 
+ Isnull(af.mins, 0) 
- Isnull(al.mins, 0)) AS FLOAT) 
* 100, 0)
AS [Actual Utilisation]

任何帮助将不胜感激。

【问题讨论】:

    标签: sql-server stored-procedures percentage divide-by-zero


    【解决方案1】:

    在我看来,最简单的方法是用NULLIF 包裹除数,这样如果它的值为0,则该值变为NULL

    例如:

    SomeColumn / NULLIF(AnotherColumn - MoreColumn,0)
    

    旁注,请考虑在编写 SQL 时良好使用空格。该代码很难阅读。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-15
      • 2016-09-04
      • 2020-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多