以日期为单位选择行作为nvarchar的更有效方法

时间:2011-09-05 11:15:48

标签: sql tsql sql-server-2008

大家好奇,是否有人可以建议一种更有效的方法从表中选择大约有6千万条记录的行。每行都有一个存储为nvarchar的日期,例如'20110527030000.106'。我想根据这个日期字段选择3个月或更早的所有行,所以例如我只对日期字段的第一部分感兴趣; '20110527'。我有以下代码来做到这一点,但它有点慢,并想知道是否有更好的方法?

DECLARE @tempDate varchar(12)
SET @tempDate = convert(varchar(12),DATEADD(m,-3,GETDATE()),112)

SELECT *
  FROM [TABLE A]
  WHERE SUBSTRING([DATE_FIELD],0,8) < @tempDate

3 个答案:

答案 0 :(得分:4)

您的查询不仅不能使用[DATE_FIELD]上的任何索引并执行完整扫描,而且还会将SUBSTRING()函数应用于表的(date_field列)的所有值。

不要在列上应用任何函数,因此可以使用[DATE_FIELD]的索引,并且在计算@tempDate时该函数仅应用一次:

SELECT *
  FROM [TABLE A]
  WHERE [DATE_FIELD] < @tempDate

<比较适用于varchar值。以下内容将评估为True

'20110526030000.106' < '20110527'

是否有任何理由datetime未存储为datetime类型?

答案 1 :(得分:1)

如果您可以修改表,则可以添加datetime列,然后运行更新以使用正确的数据填充它。

如果无法修改表,则可以创建一个带有datetime列的新表,从要查询的表中提取键,并在表中强制执行foriegn键约束。然后,您可以像以前一样弹出datetime列,然后在查询时加入表。

如果您无法修改任何内容,那么我想您可以尝试针对解决方案对您的解决方案进行基准测试,在该解决方案中,您可以动态地将varchar日期转换为日期时间(例如,使用用户定义的函数)。这可能实际上运行得更快。

希望这可以帮助你...

答案 2 :(得分:1)

如果你可以修改数据库,你可以添加一个新字段isolder3months并为每个新条目设置为1。

使用触发器,您可以每天为isolder3months = 1的每个条目更新一次。这样您只需检查/更新条目的第1个。

此解决方案仅在修复3个月并且经常使用此查询时才可用。

然后您的查询看起来像

SELECT *
FROM [TABLE A]
WHERE [isolder3months] = 1