代码之家  ›  专栏  ›  技术社区  ›  Ryan Gadsdon

日期时间上的floor()函数-SQL Server

  •  1
  • Ryan Gadsdon  · 技术社区  · 6 年前

    http://sqlfiddle.com/#!18/639ec/2

    CREATE TABLE TEST
    (
    ID INT,
    OrderNo int,
    DateReceived datetime
    )
    
    INSERT INTO TEST (ID,OrderNo,DateReceived)
    VALUES ('1', '3454', '07-20-2018 00:00:00')
    

    查询:

    DECLARE @StartDate datetime,
    @EndDate datetime,
    @FlooredStart datetime ,
    @FlooredEnd datetime 
    
    SET @StartDate = '07-20-18'
    SET @EndDate = '07-20-18'
    SET @FlooredStart  = CAST(FLOOR(CAST(@startDate AS FLOAT)) AS DATETIME)
    SET @FlooredEnd = DATEADD(d, 1, CAST(FLOOR(CAST(@endDate AS FLOAT)) AS DATETIME))
    
    SELECT * FROM TEST 
    WHERE DateReceived = @FlooredStart and DateReceived < @FlooredEnd
    

    在我的实时版本中,如果接收日期为空,则默认为当天的12:00:00。因此,对于这个示例,如果我在07-20-18上搜索订单,它将不会返回07-20-18上午12:00:00下的订单。

    因此,我想在该子句中添加>=

    DECLARE @StartDate datetime,
    @EndDate datetime,
    @FlooredStart datetime ,
    @FlooredEnd datetime 
    
    SET @StartDate = '07-20-18'
    SET @EndDate = '07-20-18'
    SET @FlooredStart  = CAST(FLOOR(CAST(@startDate AS FLOAT)) AS DATETIME)
    SET @FlooredEnd = DATEADD(d, 1, CAST(FLOOR(CAST(@endDate AS FLOAT)) AS 
    DATETIME))
    
    SELECT * FROM TEST 
    -- WHERE DateReceived BETWEEN @StartDate AND @EndDate
    WHERE DateReceived >= @FlooredStart and DateReceived < @FlooredEnd
    

    结果:

    | ID | OrderNo |         DateReceived |
    |----|---------|----------------------|
    |  1 |    3454 | 2018-07-20T00:00:00Z |
    

    我只是想知道我的逻辑是否正确?有人能给我解释一下floor()函数在做什么吗?我知道它是在计算每年/月的第一天,但这里需要吗?我在网上查了一下,找不到确切的答案。

    谢谢

    1 回复  |  直到 6 年前
        1
  •  4
  •   Panagiotis Kanavos    6 年前

    而不是使用 floor 要“截断”时间部分,请仅使用日期 date 类型:

    DECLARE @StartDate date = '20180720', @EndDate date='20180720'
    
    SELECT * FROM TEST 
    WHERE cast(DateReceived date) between @startdate and @enddate
    

    或者,对于单一日期:

    SELECT * FROM TEST 
    WHERE cast(DateReceived date) = @startdate 
    

    注意,我使用的是未分隔的日期文本。这就是 只有 明确的日期格式。另一种明确的格式是日期时间类型的完整ISO8601格式。两位数的年份只是 乞求 对于不正确的解释方式。

    cast(DateReceived date) 将转换 datetime 价值观 DateReceived 进入之内 日期 价值观。通常,这是一个 坏的 将函数应用于字段的想法,因为它阻止查询优化器使用任何索引。SQL Server了解 cast( ... as date) 虽然和转换:

    cast(DateReceived date) = @startdate 
    

    到相当于 DateReceived between @startdate at 00:00 but before the next day at 00:00 ,允许它使用上的任何索引 数据登录