Reputation: 135
I'm currently encountering an issue with dividing by zero - I'm trying to implement CASE
to just mark the divided number as "1" however, I'm still getting the error - I'm guessing I'm missing something here? Just not sure what...
SELECT
CASE WHEN c.PageCount IS NULL OR c.PageCount=0 THEN 1 ELSE c.PageCount END as [PageCount],
cast(c.PageCount / CASE WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) IS NULL OR DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) = 0 THEN 1 ELSE DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)END as decimal(5,2)) as PagesPerMinute,
CASE
WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 30 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) >= 1 THEN
CASE WHEN CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ > 45 /*minutes*/ THEN 45 ELSE CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ END
WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 60 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) < 1 /* 1 minute/page */ THEN 60
ELSE
DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
END [MinutesPaid]
FROM
tbl_Charts c
left outer join (select cd.ChartId, count(*) as CodesFound from tbl_ChartCodes cd group by cd.ChartId) cd on cd.ChartId = c.ChartId,
tbl_WFChartEvents ev,
tbl_Users u,
(select evar.ChartId, evar.ActionUserId, ar.ResultDescription, evar.ActionRemark, evar.ActionDate
from tbl_WFChartEventActions evar, tbl_WFChartEventActionResults ar
where evar.EventId = 201
and evar.ActionResultId = ar.ResultID and evar.EventId = ar.EventID
and evar.ActionTypeId = ar.ActionTypeID
and evar.EventId = 201) arr
WHERE
c.ChartId = ev.ChartId
and ev.EventId = 201
and ev.EventCreateUserId = u.UserId
and arr.ActionUserId = u.UserId
and arr.ChartId = c.ChartId
order by ev.EventCreateDate
Upvotes: 0
Views: 785
Reputation: 10908
For easier readability/maintainability of division formulas, wrap every divisor with NULLIF(x,0)
.
This is easier than checking for zeros with a case statement and ensuring the divisor is identical to the case predicate. Everywhere you see a / [...]
, make it / NULLIF( [...] ,0)
instead of this:
cast(
c.PageCount / CASE
WHEN (DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) IS NULL
OR DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) = 0
)
THEN 1
ELSE DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
END
as decimal(5,2)
) as PagesPerMinute,
do this:
cast(
coalesce(
c.PageCount / NULLIF(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate), 0)
,c.PageCount --Return this value if preceding is null or div_by_zero
)
as as decimal(5,2)
) as PagesPerMinute
Upvotes: 1
Reputation: 2016
OK, 3rd time the charm? I thought I found the problem twice, but I think I know what's going on now.
All sql I know, you can't use an aliased column else where in the select. By aliasing c.PageCount to [PageCount] I believe you are still using the original c.PageCount without the table alias. To test this out, just change [PageCount] to [PageCount2]. I suspect you will get an error it doesn't recognize the column name.
This only 'appears' to work because you reused the already unique column name from the results.
What I meant was take this case and replace the [PageCount] with it.
CASE WHEN c.PageCount IS NULL OR c.PageCount=0 THEN 1 ELSE c.PageCount END
like this
CASE
WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 30 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST(CASE WHEN c.PageCount IS NULL OR c.PageCount=0 THEN 1 ELSE c.PageCount END AS FLOAT) >= 1 THEN
CASE WHEN CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ > 45 /*minutes*/ THEN 45 ELSE CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ END
WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 60 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST(CASE WHEN c.PageCount IS NULL OR c.PageCount=0 THEN 1 ELSE c.PageCount END AS FLOAT) < 1 /* 1 minute/page */ THEN 60
ELSE
DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
END [MinutesPaid]
Upvotes: 0
Reputation: 1269883
I think your problem is in this case
statement:
CASE WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 30 AND
CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) >= 1
THEN (CASE WHEN CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ > 45 /*minutes*/
THEN 45 ELSE CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/
END)
WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 60 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) < 1 /* 1 minute/page */
THEN 60
ELSE DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
END AS [MinutesPaid]
The first when
statement has a divisision. Just rephrase this as:
CASE WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 30 AND
CAST([PageCount] AS FLOAT) > 0 AND
CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT) >= CAST([PageCount] AS FLOAT)
THEN (CASE WHEN CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ > 45 /*minutes*/
THEN 45 ELSE CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/
END)
WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 60 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) < 1 /* 1 minute/page */
THEN 60
ELSE DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
END AS [MinutesPaid]
I removed the division with a simple comparison and guarantee the value is not 0.
Upvotes: 0