我需要在Azure SQL数据库中的某个地方表示某个瞬间。我需要能够有效地查询两个事件是否在同一本地日期发生,以及任意位置的某个事件是否在另一个任意位置的另一个事件之前发生。
如果我使用DateTimeOffset
,则每次要查询本地日期是否发生了某些事情时,都必须转换为Date
,这可能意味着我将无法使用列上的索引。
如果我使用包含本地日期的Date
列,包含本地时间的Time
列和offset列,则需要将它们结合在一起以获取绝对日期时间,这可能意味着我将无法在列上使用任何索引。
如果我全部都用完它们,则可以在所有内容上都有索引,但是我的数据模型不能保证它们之间的一致性。
有没有一种方法可以对此数据建模,因此我可以高效地查询本地事件日期的相等性(例如,事件发生在本地时间的2018年12月12日,而不管可能有什么偏移量)和查询能及时有效地进行数据交换,同时又使数据模型能够使它们之间保持连贯性?
答案 0 :(得分:1)
datetimeoffset
列将使您可以有效地查询相等性和范围,只要避免转换列值即可。可以使用包含的开始值和包含的结束值来有效地完成涉及包含时间成分的时间类型的日期范围查询,而不用将其转换为日期。
下面是显示相等和范围搜索的示例。在这两种情况下都使用聚簇索引查找。
CREATE TABLE dbo.DateTimeOffsetExample (
DateTimeOffsetColumn datetimeoffset NOT NULL
);
CREATE INDEX cdx ON dbo.DateTimeOffsetExample(DateTimeOffsetColumn);
GO
INSERT INTO dbo.DateTimeOffsetExample(DateTimeOffsetColumn)
VALUES
--Central Standard Time
('2018-12-14 23:00:00.00000000 -06:00')
, ('2018-12-15 07:00:00.00000000 -06:00')
, ('2018-12-15 12:00:00.00000000 -06:00')
, ('2018-12-15 19:00:00.00000000 -06:00')
, ('2018-12-15 22:00:00.00000000 -06:00')
, ('2018-12-15 23:00:00.00000000 -06:00')
, ('2018-12-16 00:00:00.00000000 -06:00')
--Eastern Standard Time
, ('2018-12-15 00:00:00.00000000 -05:00')
, ('2018-12-15 08:00:00.00000000 -05:00')
, ('2018-12-15 13:00:00.00000000 -05:00')
, ('2018-12-15 20:00:00.00000000 -05:00')
, ('2018-12-15 23:00:00.00000000 -05:00')
, ('2018-12-16 00:00:00.00000000 -05:00')
, ('2018-12-16 01:00:00.00000000 -05:00')
--Central European Standard Time
, ('2018-12-15 06:00:00.00000000 +01:00')
, ('2018-12-15 14:00:00.00000000 +01:00')
, ('2018-12-15 19:00:00.00000000 +01:00')
, ('2018-12-16 02:00:00.00000000 +01:00')
, ('2018-12-16 05:00:00.00000000 +01:00')
, ('2018-12-16 06:00:00.00000000 +01:00')
, ('2018-12-16 07:00:00.00000000 +01:00')
--SE Asia Standard Time
, ('2018-12-15 12:00:00.00000000 +07:00')
, ('2018-12-15 20:00:00.00000000 +07:00')
, ('2018-12-16 01:00:00.00000000 +07:00')
, ('2018-12-16 08:00:00.00000000 +07:00')
, ('2018-12-16 11:00:00.00000000 +07:00')
, ('2018-12-16 12:00:00.00000000 +07:00')
, ('2018-12-16 13:00:00.00000000 +07:00');
GO
平等:
--equality (clustered index seek using equality predicate)
DECLARE @LocalTime datetimeoffset = '2018-12-15 00:00:00.00000000 -05:00';
SELECT *
FROM dbo.DateTimeOffsetExample
WHERE DateTimeOffsetColumn = @LocalTime;
+------------------------------------+
| DateTimeOffsetColumn |
+------------------------------------+
| 2018-12-14 23:00:00.0000000 -06:00 |
| 2018-12-15 00:00:00.0000000 -05:00 |
| 2018-12-15 06:00:00.0000000 +01:00 |
| 2018-12-15 12:00:00.0000000 +07:00 |
+------------------------------------+
单个日期的范围查询:
--range (clustered index seek using range predicate)
DECLARE
@LocalTimeStart datetimeoffset = '2018-12-15 00:00:00.00000000 -05:00'
, @LocalTimeEnd datetimeoffset = '2018-12-16 00:00:00.00000000 -05:00';
SELECT *
FROM dbo.DateTimeOffsetExample
WHERE DateTimeOffsetColumn >= @LocalTimeStart
AND DateTimeOffsetColumn < @LocalTimeEnd;
+------------------------------------+
| DateTimeOffsetColumn |
+------------------------------------+
| 2018-12-14 23:00:00.0000000 -06:00 |
| 2018-12-15 00:00:00.0000000 -05:00 |
| 2018-12-15 06:00:00.0000000 +01:00 |
| 2018-12-15 12:00:00.0000000 +07:00 |
| 2018-12-15 07:00:00.0000000 -06:00 |
| 2018-12-15 08:00:00.0000000 -05:00 |
| 2018-12-15 14:00:00.0000000 +01:00 |
| 2018-12-15 20:00:00.0000000 +07:00 |
| 2018-12-15 12:00:00.0000000 -06:00 |
| 2018-12-15 13:00:00.0000000 -05:00 |
| 2018-12-15 19:00:00.0000000 +01:00 |
| 2018-12-16 01:00:00.0000000 +07:00 |
| 2018-12-15 19:00:00.0000000 -06:00 |
| 2018-12-15 20:00:00.0000000 -05:00 |
| 2018-12-16 02:00:00.0000000 +01:00 |
| 2018-12-16 08:00:00.0000000 +07:00 |
| 2018-12-15 22:00:00.0000000 -06:00 |
| 2018-12-15 23:00:00.0000000 -05:00 |
| 2018-12-16 05:00:00.0000000 +01:00 |
| 2018-12-16 11:00:00.0000000 +07:00 |
+------------------------------------+