0

我正在从不同的系统导入数据,并且日期时间以这种格式存储为字符串:

20061105084755ES

yyyymmddhhmmss(es/ed)esEST 和edEDT在哪里。

我将不得不在过去 30 天内查询此表。我正在使用转换查询:

select convert(
    datetime,
    left(cdts, 4)+'-'+substring(cdts, 5,2)+'-'substring(cdts, 7,2)+' '+substring(cdts, 9,2) +':'+substring(cdts, 11,2)+':'+substring(cdts, 13,2)
as dt
from tb1
where dt < getdate()-30

我正在寻找一种更有效的查询来减少所花费的时间。该表有大约 9000 万条记录,并且查询永远运行。

4

3 回答 3

2

如果您正在执行计算然后需要根据计算结果进行过滤,则运行时的任何计算都不会加速此查询 - SQL Server 将被迫执行表扫描。主要问题是您选择将日期存储为字符串。由于各种原因,这是一个糟糕的决定。字符串列是否至少被索引?如果是这样,那么这可能有助于仅获取过去 30 天的数据:

DECLARE @ThirtyDays CHAR(8);
SET @ThirtyDays = CONVERT(CHAR(8),DATEADD(DAY,DATEDIFF(DAY,0,GETDATE()),0)-30,112);

SELECT ...
WHERE cdts >= @ThirtyDays;

如果您需要从除过去 30 天之外的所有历史记录中返回所有数据,这也无济于事,因为除非您仅从索引列中提取数据,否则检索大多数数据的最有效方法该表是使用聚集索引扫描。(如果您要检索一组狭窄的列,如果您有一个覆盖索引,它可能会选择索引扫描。)因此,在大多数情况下,您的瓶颈不是公式可以解决的问题,而是它所花费的时间实际检索大量数据,通过网络传输,然后在客户端呈现。

另外,顺便说一句,你不能这样做:

SELECT a + b AS c FROM dbo.somewhere
WHERE c > 10;

c中不存在,它是从列表中dbo.somewhere派生的表达式。SELECTSELECT列表被解析为倒数第二个(就在 之前ORDER BY),因此您不能引用该WHERE子句中尚不存在的内容。典型的解决方法是重复表达式或使用子查询/CTE。

于 2013-08-23T17:58:47.593 回答
1

一种可能的选择是将日期列添加到表中并在加载时填充该信息。这样,转换就在您需要查询之前完成。

然后,确保您在该字段上有一个实际查询可以利用的索引。

于 2013-08-23T17:36:54.047 回答
0
convert(datetime,stuff(stuff(stuff(datevalue, 9, 0, ' '), 12, 0, ':'), 15, 0, ':'))

或者

    Convert(time,Dateadd(SECOND,
        Right(DateValue,2)/1,
        Dateadd(MINUTE,
                Right(DateValue,4)/100,
                Dateadd(hour,
                        Right(DateValue,6)/10000,
                        '1900-01-01')))) +
convert(datetime,LEFT(datevalue,8))

关联

于 2013-08-23T17:39:08.053 回答