如何在 SELECT 和 WHERE 子句中使用 CASE 来消除被零除的问题
How to use CASE in SELECT and WHERE clause to Eliminate divide by zero issue
使用 SQL Server 2008 R2,我有一个查询,现在给我除以零的错误。这是因为 DB 列值始终应该 > 0。这已更改。该列为 wf.reminderFrequency
,现在设置为无空值,默认值为 0。
这里是查询:
SELECT
wfi.WebFormsInstanceID AS instanceID,
wfi.FormActionDate as fLastActionDate,
wf.reminderFrequency as fReminderFeq,
DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),
CAST(GETDATE() AS DATE)) AS theDateDiffCalc,
DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),
CAST(GETDATE() AS DATE)) % wf.reminderFrequency AS theModCalc
FROM
(webFormsInstances as wfi
LEFT OUTER JOIN
WebFormsIndex as wf ON wfi.WebFormsIndexID = wf.WebFormsIndexID)
WHERE
(wfi.formStage <> 'Complete'
AND wfi.FormStage <> 'Terminated'
AND wfi.FormStage <> 'Payroll Processing')
AND (wfi.FormActionDate > 20150101)
AND (DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE), CAST(GETDATE() AS DATE)) % wf.reminderFrequency = 0)
ORDER BY
wfi.WebFormsInstanceID DESC;
该查询旨在获取所有 WebFormsIndex 记录,其中 X (wf.reminderFrequency) 天没有发生任何操作(今天和 fLastActionDate 之间的差异)。请注意 - 查询比它需要的更混乱,因为 fLastActionDate 是一个 YYYYMMDD 整数值,不幸的是不能更改。那么我该如何更改它以处理 wf.reminderFrequency 现在可以为 0 的情况。正如您所看到的,该值在查询的两个部分中使用。
这是我对 SELECT 部分的解决方案,我认为它会起作用:
SELECT
wfi.WebFormsInstanceID AS instanceID,
wfi.WebFormsIndexID as fID,
wf.FormName as fName,
wfi.FormOwner as fOwner,
wfi.FormStage as fStage,
wfi.FormAction as fAction,
wfi.FormActionDate as fLastActionDate,
wf.reminderFrequency,
wfi.Comments as fComments,
DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),
CAST(GETDATE() AS DATE)) AS theDateDiffCalc,
CASE
WHEN wf.reminderFrequency > 0
THEN
DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE), CAST(GETDATE() AS DATE)) % wf.reminderFrequency
ELSE
'-1'
END AS theModCalc
FROM
(webFormsInstances as wfi
但是我没有运气弄清楚如何处理 WHERE
子句中的除法。
这不起作用:
WHERE
(wfi.formStage <> 'Complete'
AND wfi.FormStage <> 'Terminated'
AND wfi.FormStage <> 'Payroll Processing')
AND (wfi.FormActionDate > 20150101)
CASE
WHEN wf.reminderFrequency > 0
THEN
AND (DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE), CAST(GETDATE() AS DATE)) % wf.reminderFrequency = 0)
END AS
ORDER BY
wfi.WebFormsInstanceID DESC;
UPDATE - 来自第一个语句的示例数据:
instanceID fLastActionDate fReminderReq theDateDiffCalc theModCalc
24965 20150312 14 14 0
24965 20150312 14 14 0
24940 20150226 14 28 0
感谢@Gordon 使用 nullif 是解决方案。似乎工作得很好。它在 select:
中是这样使用的
DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),CAST(GETDATE() AS DATE)) % nullif(wf.reminderFrequency,0) AS theModCalc
在 WHERE 中也是如此:
AND (DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),CAST(GETDATE() AS DATE)) % nullif(wf.reminderFrequency,0) = 0)
如果您可以将 NULL
作为值而不是 -1
,我会推荐 NULLIF()
:
DATEDIFF(day,
CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),
CAST(GETDATE() AS DATE)
) % nullif(wf.reminderFrequency, 0) AS theModCalc
这将适用于 select
和 where
。
使用 SQL Server 2008 R2,我有一个查询,现在给我除以零的错误。这是因为 DB 列值始终应该 > 0。这已更改。该列为 wf.reminderFrequency
,现在设置为无空值,默认值为 0。
这里是查询:
SELECT
wfi.WebFormsInstanceID AS instanceID,
wfi.FormActionDate as fLastActionDate,
wf.reminderFrequency as fReminderFeq,
DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),
CAST(GETDATE() AS DATE)) AS theDateDiffCalc,
DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),
CAST(GETDATE() AS DATE)) % wf.reminderFrequency AS theModCalc
FROM
(webFormsInstances as wfi
LEFT OUTER JOIN
WebFormsIndex as wf ON wfi.WebFormsIndexID = wf.WebFormsIndexID)
WHERE
(wfi.formStage <> 'Complete'
AND wfi.FormStage <> 'Terminated'
AND wfi.FormStage <> 'Payroll Processing')
AND (wfi.FormActionDate > 20150101)
AND (DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE), CAST(GETDATE() AS DATE)) % wf.reminderFrequency = 0)
ORDER BY
wfi.WebFormsInstanceID DESC;
该查询旨在获取所有 WebFormsIndex 记录,其中 X (wf.reminderFrequency) 天没有发生任何操作(今天和 fLastActionDate 之间的差异)。请注意 - 查询比它需要的更混乱,因为 fLastActionDate 是一个 YYYYMMDD 整数值,不幸的是不能更改。那么我该如何更改它以处理 wf.reminderFrequency 现在可以为 0 的情况。正如您所看到的,该值在查询的两个部分中使用。
这是我对 SELECT 部分的解决方案,我认为它会起作用:
SELECT
wfi.WebFormsInstanceID AS instanceID,
wfi.WebFormsIndexID as fID,
wf.FormName as fName,
wfi.FormOwner as fOwner,
wfi.FormStage as fStage,
wfi.FormAction as fAction,
wfi.FormActionDate as fLastActionDate,
wf.reminderFrequency,
wfi.Comments as fComments,
DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),
CAST(GETDATE() AS DATE)) AS theDateDiffCalc,
CASE
WHEN wf.reminderFrequency > 0
THEN
DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE), CAST(GETDATE() AS DATE)) % wf.reminderFrequency
ELSE
'-1'
END AS theModCalc
FROM
(webFormsInstances as wfi
但是我没有运气弄清楚如何处理 WHERE
子句中的除法。
这不起作用:
WHERE
(wfi.formStage <> 'Complete'
AND wfi.FormStage <> 'Terminated'
AND wfi.FormStage <> 'Payroll Processing')
AND (wfi.FormActionDate > 20150101)
CASE
WHEN wf.reminderFrequency > 0
THEN
AND (DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE), CAST(GETDATE() AS DATE)) % wf.reminderFrequency = 0)
END AS
ORDER BY
wfi.WebFormsInstanceID DESC;
UPDATE - 来自第一个语句的示例数据:
instanceID fLastActionDate fReminderReq theDateDiffCalc theModCalc
24965 20150312 14 14 0
24965 20150312 14 14 0
24940 20150226 14 28 0
感谢@Gordon 使用 nullif 是解决方案。似乎工作得很好。它在 select:
中是这样使用的 DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),CAST(GETDATE() AS DATE)) % nullif(wf.reminderFrequency,0) AS theModCalc
在 WHERE 中也是如此:
AND (DATEDIFF(day, CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),CAST(GETDATE() AS DATE)) % nullif(wf.reminderFrequency,0) = 0)
如果您可以将 NULL
作为值而不是 -1
,我会推荐 NULLIF()
:
DATEDIFF(day,
CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE),
CAST(GETDATE() AS DATE)
) % nullif(wf.reminderFrequency, 0) AS theModCalc
这将适用于 select
和 where
。