SQL选择查询中的日期范围

时间:2018-11-06 20:31:13

标签: sql sql-server tsql

我的SQL数据库每天对Access数据库中的所有记录进行备份,并用“ Logtime”字段(格式为datetime)指示备份时间。我的SQL数据库的重点是存储Access数据库记录的所有版本。例如,如果Access数据库中的条目已更改,则可以在SQL中查看该条目的所有版本,并确定更改的内容和时间。我正在使用下面的查询从我的SQL数据库中选择记录,但一次只能使用一个日期。由于“ Logtime”字段是将记录组合​​在一起的唯一标识符,因此我不确定如何查询日期范围而不会提取错误的重复记录。我非常感谢社区可以提供的任何帮助。如果可以任何方式澄清我的问题,请告诉我。

DECLARE @theDate varchar(60)
SET @theDate = '10/31/2018'

SELECT        dbo.tbl_EquipmentRequests.Logtime, dbo.tbl_EquipmentRequests.[Equipment Request ID], dbo.tbl_EquipmentRequests.[TrackIT Number], dbo.tbl_EquipmentRequests.[Requestor name:], 
                         dbo.tbl_EquipmentRequests.[Requestor email:], dbo.tbl_EquipmentRequests.[Entered on:], dbo.tbl_EquipmentRequests.[Approver name:], dbo.tbl_EquipmentRequests.[Approver email:], 
                         dbo.tbl_EquipmentRequests.Status, dbo.tbl_EquipmentRequests.Notes, dbo.[tbl_IT Staff].[IT Staff Member], dbo.tbl_Order_Types.[Order Type], dbo.tbl_EquipReqDetails.Vendor, dbo.tbl_EquipReqDetails.Quantity, 
                         dbo.tbl_EquipReqDetails.[Unit Price], dbo.tbl_EquipReqDetails.[Account Code], dbo.tbl_EquipReqDetails.Status AS Expr1, dbo.tbl_EquipReqDetails.[Vendor Invoice #], 
                         dbo.tbl_EquipReqDetails.[Invoice approved by Tom], dbo.tbl_EquipReqDetails.[Invoice date], dbo.tbl_EquipReqDetails.[Invoice sent to AP on], dbo.tbl_EquipReqDetails.Notes AS Expr2, 
                         dbo.tbl_Equipment.[Equipment Description]
FROM            dbo.tbl_EquipmentRequests INNER JOIN
                         dbo.[tbl_IT Staff] ON dbo.tbl_EquipmentRequests.[Entered by:] = dbo.[tbl_IT Staff].ID INNER JOIN
                         dbo.tbl_Order_Types ON dbo.tbl_EquipmentRequests.[Order Type] = dbo.tbl_Order_Types.ID INNER JOIN
                         dbo.tbl_EquipReqDetails ON dbo.tbl_EquipmentRequests.[Equipment Request ID] = dbo.tbl_EquipReqDetails.[Equipment Request ID] INNER JOIN
                         dbo.tbl_Equipment ON dbo.tbl_EquipReqDetails.[Equipment ID] = dbo.tbl_Equipment.ID
WHERE        (CAST(dbo.tbl_EquipmentRequests.Logtime AS date) = @theDate) AND (CAST(dbo.[tbl_IT Staff].Logtime AS date) = @theDate) AND (CAST(dbo.tbl_Order_Types.Logtime AS date) = @theDate) AND 
                         (CAST(dbo.tbl_EquipReqDetails.Logtime AS date) = @theDate) AND (CAST(dbo.tbl_Equipment.Logtime AS date) = @theDate)

1 个答案:

答案 0 :(得分:0)

假设您的时区都相同(建议不要保存时区而不使时区透明-建议使用UTC),然后也使用正确的数据类型(对所有内容使用字符串都是非常不好)。 我也强烈建议使用ISO-8601格式,因为它是明确的且采用高位优先(这使天真的字符串排序变得非常容易)。

确定日期后,只需将其添加24小时即可获取第二天的午夜并进行范围查询(使用SQL Server语法):

DECLARE @FilterDate DATE = '2018-10-31'
DECLARE--implicit conversions to DATETIME type here:
     @FilterStart DATETIME = @FilterDate
    ,@FilterEnd DATETIME = DATEADD(DAY, 1, @FilterDate)

SELECT ...
FROM ...
WHERE
    @FilterStart <= LogTime
    AND LogTime < @FilterEnd

请注意,时间范围的末尾如何不使用LessOrEqual运算符,因为第二天的午夜不在您指定的日期,而是包括了之前的每个 epsilon (您不会如果您想避免使用make assumptions about precision of your data types,则不要使用BETWEEN来将两个边界都包括在内。 如果您将时间戳记用作唯一标识符,则由于这个原因您将经历一段糟糕的时光(更不用说竞争条件了。)请改用外键/自动增量列。

还要注意WHERE子句中没有应用任何函数(也请避免在join子句中使用它们),这使SQL引擎可以利用行上的任何索引。 Otherwise casting your LogTime values to DATE would prevent index use