如何在 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 

这将适用于 selectwhere