如何从日期/时间字段SQL Server快速选择DISTINCT日期

ruq*_*uay 8 sql-server datetime distinct

我想知道是否有一个性能良好的查询从SQL Server中的日期时间字段的表中选择不同的日期(忽略时间).

我的问题是没有让服务器实际执行此操作(我已经看过这个问题了,我们已经使用DISTINCT进行了类似的操作).问题在于是否有任何技巧可以更快地完成任务.使用我们正在使用的数据,我们当前的查询返回大约80个不同的日子,其中有大约40,000行数据(在另一个索引列上过滤后),日期列上有一个索引,查询总是设法采取5秒以上.这太慢了.

更改数据库结构可能是一种选择,但不太令人满意.

Sco*_*ski 9

我用过以下内容:

CAST(FLOOR(CAST(@date as FLOAT)) as DateTime);
Run Code Online (Sandbox Code Playgroud)

这将从日期中删除时间,将其转换为a float并截断"时间"部分,即时间的小数float.

看起来有点笨重,但在我整天使用的大型数据集(~100,000行)上效果很好.


Rem*_*anu 6

在datetime字段上涉及CAST或TRUNCATE或DATEPART操作的每个选项都有同样的问题:查询必须扫描整个结果集(40k)才能找到不同的日期.各种实施方案之间的表现可能略有不同.

你真正需要的是拥有一个可以瞬间产生响应的索引.您可以使用持久计算列和索引(需要表结构更改)或索引视图(需要Enterprise Edition for QO才能考虑开箱即用的索引).

持久计算列:

alter table foo add date_only as convert(char(8), [datetimecolumn], 112) persisted;
create index idx_foo_date_only on foo(date_only);
Run Code Online (Sandbox Code Playgroud)

索引视图:

create view v_foo_with_date_only
with schemabinding as 
select id
    , convert(char(8), [datetimecolumn], 112) as date_only
from dbo.foo;   
create unique clustered index idx_v_foo on v_foo_with_date_only(date_only, id);
Run Code Online (Sandbox Code Playgroud)

更新

要完全消除扫描,可以使用GROUP BY欺骗索引视图,如下所示:

create view v_foo_with_date_only
with schemabinding as 
select
    convert(char(8), [d], 112) as date_only
    , count_big(*) as [dummy]
from dbo.foo
group by convert(char(8), [d], 112)

create unique clustered index idx_v_foo on v_foo_with_date_only(date_only)
Run Code Online (Sandbox Code Playgroud)

查询select distinct date_only from foo将使用此索引视图.仍然是技术上的扫描,但在已经"不同"的索引上,因此只扫描所需的记录.我认为这是一个黑客,我不会推荐它用于实时生产代码.

AFAIK SQL Server无法通过跳过重复来扫描真正的索引,即.寻求顶部,然后寻求超过顶部,然后成功寻求比最后发现更大.


小智 5

这对我有用:

SELECT distinct(CONVERT(varchar(10), {your date column}, 111)) 
FROM {your table name}
Run Code Online (Sandbox Code Playgroud)