在选择中使用Cast作为Decimal和Mod

时间:2015-02-10 00:39:17

标签: sql sql-server tsql sql-server-2008-r2

我的目标是在两个选定的字段上执行两次计算。 formActionDate是一个整数,因此YYYMMDDreminderFrequency也是一个整数(表示天数的整数)。我想将整数日期除以天数。使用mod(我认为这是最好的方法)我将决定是否需要发送电子邮件。 EG如果剩下那么就不要发送电子邮件,或者如果没有留下电子邮件就会消失。使用 SQL 2008 R2 我在我的选择中有这个:

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

注意 - 查询运行没有问题,但计算都是   出。我是否正确使用过它们?

第一个:

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

这样做: 因此:20150123 / 14应为1439294.5,但1439294.020150115 / 141439293.9应该1439293.0坚持其formActionDate%reminderFrequency AS modCalc

然后是第二个::

20150123%14

使用上面相同的例子: 因此:5应为13,但20150115%1497应为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; ,但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

感谢你......

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

{{1}}

{{1}}

3 个答案:

答案 0 :(得分:2)

当您将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

答案 1 :(得分:1)

通过检查您的查询,有一个不必要的括号。所以我删除了它。我还修改了它将如何获得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;

答案 2 :(得分:0)

尝试在分裂之前进行演员,而不是之后。而不是

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,而在我的测试中则为。