日期时间的 Floor() 函数 - SQL 服务器
Floor() function on a datetime - SQL Server
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:00AM。因此对于这个例子,如果我在 07-20-18 搜索订单,它不会 return 放置在 07-20-18 12:00:00AM 的订单。
所以我想在子句中添加 >=
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() 函数在做什么。我知道它计算 year/month 的第一天,但这里需要吗?我在网上查了一下,到处都找不到明确的答案。
谢谢
不要使用 floor
到 "truncate" 时间部分,而是使用仅日期 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
请注意,我使用的是未分隔的日期文字。这是 only 明确的日期格式。另一种明确的格式是日期时间类型的完整 ISO8601 格式。两位数的年份只是乞求不正确的解释方式。
cast(DateReceived date)
会将 DateReceived
中的 datetime
值转换为 date
值。通常,将函数应用于字段是一个 糟糕 的想法,因为它会阻止查询优化器使用任何索引。 SQL 服务器理解 cast( ... as date)
并转换 :
cast(DateReceived date) = @startdate
相当于 DateReceived between @startdate at 00:00 but before the next day at 00:00
的范围查询,允许它使用 DateReceived
上的任何索引
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:00AM。因此对于这个例子,如果我在 07-20-18 搜索订单,它不会 return 放置在 07-20-18 12:00:00AM 的订单。
所以我想在子句中添加 >=
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() 函数在做什么。我知道它计算 year/month 的第一天,但这里需要吗?我在网上查了一下,到处都找不到明确的答案。
谢谢
不要使用 floor
到 "truncate" 时间部分,而是使用仅日期 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
请注意,我使用的是未分隔的日期文字。这是 only 明确的日期格式。另一种明确的格式是日期时间类型的完整 ISO8601 格式。两位数的年份只是乞求不正确的解释方式。
cast(DateReceived date)
会将 DateReceived
中的 datetime
值转换为 date
值。通常,将函数应用于字段是一个 糟糕 的想法,因为它会阻止查询优化器使用任何索引。 SQL 服务器理解 cast( ... as date)
并转换 :
cast(DateReceived date) = @startdate
相当于 DateReceived between @startdate at 00:00 but before the next day at 00:00
的范围查询,允许它使用 DateReceived