1

我的 dbase 具有 6 位数的日期格式和 int 数据类型('734503' = 01/01/2012)。我已经能够成功地将这些转换为字符:

SELECT CONVERT(char(12),dateadd(dd,(date_paid -    639906),'1/1/1753'),101)  
FROM   vouchers       
WHERE date_paid =    '734503'

这给了我 2012 年 1 月 1 日的输出。但是,如果我在这样的查询中搜索转换后的日期:

SELECT CONVERT(char(12),dateadd(dd,(date_paid - 639906),'1/1/1753'),101) 
FROM vouchers    
WHERE date_paid >= '09/01/2012'  AND date_paid <= '09/30/2012'

为什么没有发生转换?即使我在 date_paid 字段的 WHERE 语句中使用 CONVERT,它不应该在那里工作吗?

我想我的问题是如何使用转换后的字符日期进行搜索而不必使用 6 位日期?

4

2 回答 2

1

您的问题是您正在将 INT 列与 STRING 值进行比较,并希望它能够像比较日期一样解决......

WHERE date_paid >= '09/01/2012'
  AND date_paid <= '09/30/2012' 

-- date_paid is an INT (according to your question)
-- '09/01/2012' is a STRING

由于不同的数据类型,那里有一个隐式的CAST() 。实际上你正在做...

WHERE CAST(date_paid AS VARCHAR(10)) >= '09/01/2012'
  AND CAST(date_paid AS VARCHAR(10)) <= '09/30/2012' 

-- NOTE:  All of these values are now strings
--        They may LOOK like dates, but they're just strings

您真正需要做的是将字符串显式操作为整数。

WHERE date_paid >= DATEDIFF(DAY, '01/01/1753', '09/01/2012') + 639906
  AND date_paid <= DATEDIFF(DAY, '01/01/1753', '09/30/2012') + 639906

这也涉及隐式强制转换。DATEDIFF() 仅采用 DATETIME 数据类型,因此首先将字符串隐式转换为 DATETIME。

编辑:

另一种选择是将date_paid字段 CAST() 转换为 DateTime,然后以此为基础WHERE。这里
的缺点是...... - CAST() 必须在每一行上完成,然后应用 WHERE 子句
- 这可以防止任何索引的使用并显着降低性能

上面的答案对常量值进行了所有操作,以便可以在其本机状态下处理搜索到的字段;从而允许使用索引。

于 2012-10-19T15:32:05.607 回答
1

首先,如果可以的话,改变你的数据库模式。date_paid 列的数据类型应该是datetimeor date,而不是 'int' 或 'char'。

...但是如果您坚持使用此模式,那么您的date_paid值似乎是整数,其中 693596 的值表示1 jan 1900. (此日期是 SQL Server 零值映射到的位置。)因此,您需要做的就是将搜索值移动或偏移该数量。

假设您要搜索的日期是今天,2012 年 10 月 19 日

 Declare @SearchDate DateTime = '20 Oct 2012'

然后将您的查询谓词编写为:

  Select * From vouchers
  Where date_paid = DateDiff(day, 0, @searchDate) + 693596 

确保构建查询结构,以便所有处理或计算都在列等号的另一date_paid侧完成(如我的示例所示)。这样,查询处理器可以使用索引date_Paid是否存在。如果查询有任何函数调用或其他计算date_Paid,则查询将不得不读取整个表并且不能使用其他可用的索引请参阅SARGable

顺便说一句,我很好奇这个设计(用这么大的整数来表示日期)的确切来源,我注意到这个值正好等于 1900 * 365,这意味着在这个方案中,一个零值 reptresetns 零年(基督出生时)的 1 月 1 日,这很酷,但不能在 SQL Server 日期中使用它,因为 SQL Server 值将日期表示为 16 位有符号整数,映射为零到 1900 年 1 月 1 日,并且仅限于 16 位整数 (-16,384) 中的最小值,这等于 1753 年左右的某个日期。

于 2012-10-19T15:40:15.407 回答