我有一个包含以下结构的表:
create table MyTable (
ID int identity,
Whatever varchar(100),
MyTime time(2) not null,
MyDate date not null,
MyDateTime AS (DATEADD(DAY, DATEDIFF(DAY, '19000101', [MyDate]),
CAST([MyDate] AS DATETIME2(2))))
)
计算列将日期和时间添加到单个datetime2字段中。针对该表的大多数查询都有以下一个或多个子句:
... WHERE MyDate < @filter1 and MyDate > @filter2
... ORDER BY MyDate, MyTime
... ORDER BY MyDateTime
简而言之,Date通常用于过滤,完整的日期时间用于排序。现在提问:
答案 0 :(得分:4)
很遗憾,您没有提到您正在使用的SQL Server的版本 ....
但如果您使用的是SQL Server 2008或更新,那么您应该转过来:
你的桌子应该有
MyDateTime DATETIME
然后将“only date”列定义为
MyDate AS CAST(MyDateTime AS DATE) PERSISTED
由于您将其设置为持久,因此它会存储在表数据旁边(现在每次查询时都会计算),您现在可以轻松地将其编入索引。
同样适用于MyTime
列。
答案 1 :(得分:2)
在两个单独的列中包含日期和时间可能看起来很奇怪,但如果您的查询只使用日期(和/或特别是时间部分),我认为这是一个有效的决定。您可以仅在日期或按时或在(日期,等等)上创建索引等。
我不明白为什么你也有计算的日期时间列。也没有理由存储这个值。它可以在需要时轻松计算。
如果您需要按日期时间订购,则可以使用ORDER BY MyDate, MyTime
。使用(MyDate, MyTime)
上的索引,这应该没问题。范围日期时间查询也将使用该索引。
答案 2 :(得分:1)
答案不在您的索引中,而是在您的查询中。
应使用单个DateTime
字段,如果提供应用程序所需的日期和时间分辨率,则应使用SmallDateTime
。
索引该列,然后使用如下查询:
SELECT * FROM MyTable WHERE
MyDate >= @startfilterdate
AND MyDate < DATEADD(d, 1, @endfilterdate);
通过在结束过滤器上使用<
,它仅包含该日期午夜之前的某个时间的结果,该日期是用户选择的结束日期&#34;之后的第二天。这比添加23:59:59更简单,更准确,特别是因为存储的时间可以包括23:59:59到00:00:00之间的微秒。
在它们上使用持久化列和索引会浪费服务器资源。