在 Select 中使用 Cast 作为 Decimal 和 Mod

Using Cast as Decimal and Mod in Select

我的 objective 是对两个 selected 字段执行两次计算。 formActionDate 是一个像 YYYMMDD 这样的整数,reminderFrequency 也是一个整数(代表天数的整数)。我想将整数日期除以天数。使用 mod(我认为这是最好的方法)我将决定是否需要发送电子邮件。例如,如果有剩余则不要发送电子邮件,或者如果没有剩余则电子邮件会消失。使用 SQL 2008 R2 我的 select:

SELECT 
      CAST(wfi.formActionDate/wf.reminderFrequency AS DECIMAL(18,1)) AS divCalc, 
      formActionDate%reminderFrequency AS modCalc
FROM (webFormsInstances AS wfi

Note - The query is running no problem but the calculations are both out. Have I used them correctly?

第一个:

CAST(wfi.formActionDate/wf.reminderFrequency AS DECIMAL(18,3)) AS divCalc  

正在这样做: 结果: 20150123 / 14 应该是 1439294.5 但它是 1439294.020150115 / 14 应该是 1439293.9 坚果它的 1439293.0

然后是第二个::

formActionDate%reminderFrequency AS modCalc

要使用上面相同的例子: 结果:20150123%14 应该是 5 但它是 1320150115%14 应该是 9 但它是 7

我做错了什么?如果有帮助,这是我的完整查询:

SELECT 
      wfi.WebFormsInstanceID, 
      wfi.WebFormsIndexID, 
      wfi.FormStage,
      wfi.FormAction, 
      wfi.FormActionDate, 
      wf.WebFormsIndexID, 
      wf.reminderFrequency,
      CAST(wfi.formActionDate/wf.reminderFrequency AS DECIMAL(18,1)) AS divCalc, 
      formActionDate%reminderFrequency AS modCalc
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.formActionDate < CONVERT(int, CONVERT(varchar(8), dateAdd(day,-14, getdate()), 112))
ORDER BY wfi.WebFormsInstanceID DESC;

谢谢你...

已编辑。感谢 Rigel1121 和 Dave G 现在在我的 select 中的两个解决方案是:

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

尝试在除法之前做演员表,而不是之后。而不是

CAST(wfi.formActionDate/wf.reminderFrequency AS DECIMAL(18,1))

使用

wfi.formActionDate/CAST(wf.reminderFrequency AS DECIMAL(18,1))

两个整数相除得到一个整数(截去任何小数部分)。例如,SELECT 5 / 2;2(不是 2.5)。如果将除法 (2) 的结果转换为 DECIMAL(3,1),您将得到 2.0,因为截断是除法的一部分。

但是,如果您在除法之前将其中一个操作数转换为小数,则除法的结果将不是整数,也不会丢失小数部分。 SELECT 5 / CAST(2 as DECIMAL(3,1));2.5.

对于 mod,20150123 % 14 应该得到 7 而 20150115 % 14 应该得到 13,在我的测试中他们确实如此。

当您将 int 与另一个 int 相除时,结果也将是 int。您需要先将其中一个或两个参数都转换为 decimal。例如:

SELECT CAST(wfi.formActionDate AS DECIMAL(18,1)) / 
       CAST(wf.reminderFrequency AS DECIMAL(18,1)) as divCalc
...snip...

关于 mod 计算,您的数学不适用于该格式的日期。您需要将 int 转换为真实的 datetime 值,获取与基准日期的差值,然后对该值使用 mod。例如,要将该值作为日期,您可以先将其转换为 varchar,然后将其转换为 date:

DECLARE @datevalue int = 20150209

SELECT DATEDIFF(DAY, '2000-01-01', CAST(CAST(@datevalue AS VARCHAR(8)) AS DATE))%14

通过检查您的查询,发现有一个不必要的括号。所以我删除了它。我还修改了如何获取 divCalc 的值。我 CAST 分子和分母,我把它放在 CASE 语句中,以防止 wf.reminderFrequency 的值为零时出现 SQL 错误。我还使用 DATEDIFF 函数来获取 modCalc。见下文:

SELECT 
      wfi.WebFormsInstanceID, 
      wfi.WebFormsIndexID, 
      wfi.FormStage,
      wfi.FormAction, 
      wfi.FormActionDate, 
      wf.WebFormsIndexID, 
      wf.reminderFrequency,
      CASE WHEN CAST(wf.reminderFrequency AS DECIMAL(18,1))=0.0 THEN 0.0 ELSE CAST(wfi.formActionDate AS DECIMAL(18,1)) / CAST(wf.reminderFrequency AS DECIMAL(18,1)) END as divCalc, 
     DATEDIFF(DAY, '2000-01-01', CAST(CAST(wfi.formActionDate AS VARCHAR(8)) AS DATE)%wf.reminderFrequency as modCalc
      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.formActionDate < CONVERT(int, CONVERT(varchar(8), dateAdd(day,-14, getdate()), 112))
ORDER BY wfi.WebFormsInstanceID DESC;