【问题标题】:Date ranges in SQL select querySQL 选择查询中的日期范围
【发布时间】:2019-04-10 07:09:24
【问题描述】:

My SQL 数据库每天对 Access 数据库中的所有记录进行备份,并使用“Logtime”字段(格式为日期时间)指示备份时间。我的 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)

【问题讨论】:

  • 请用您的 SQL 数据库(MS Access?)标记您的帖子。 “SQL”是一个通用术语,不是数据库平台。
  • @Elaskanator 我正在运行 SSMS 2017,这算不算?
  • = 更改为>=<=。似乎是您所需要的一切。并将日期存储为date 而不是varchar
  • SQL Server Management Studio (SSMS) 能够查询各种数据库平台(例如 Azure),而不仅仅是 SQL Server。您应该能够通过检查服务器名称后括号中的前几个单词或服务器属性的“常规”选项卡下的“产品”字段来判断对象资源管理器。

标签: sql sql-server tsql


【解决方案1】:

假设您的时区都是相同的(永远不要在不使时区透明的情况下保存时间数据 - 建议使用 UTC),然后也使用正确的数据类型(对所有内容都使用字符串 非常 em>坏)。 我也强烈推荐使用 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 子句中没有应用任何函数(也避免在连接子句中使用它们),这允许 SQL 引擎利用行上的任何索引。 Otherwise casting your LogTime values to DATE would prevent index use.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多