大家好奇,是否有人可以建议一种更有效的方法从表中选择大约有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
答案 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