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 AM下达的订单。
所以我想在子句中添加> =
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()函数的作用。我知道它计算的是一年/月的第一天,但是这里需要吗?我在网上看了,却找不到任何地方的明确答案。
谢谢
答案 0 :(得分:4)
不要使用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
请注意,我使用的是未分隔的日期文字。这是 only 唯一的日期格式。另一种明确的格式是日期时间类型的完整ISO8601格式。两位数的年份只是乞求,用于错误的解释方式。
cast(DateReceived date)
将datetime
中的DateReceived
值转换为date
值。通常,将函数应用于字段是一个 bad 想法,因为这会阻止查询优化器使用任何索引。 SQL Server可以理解cast( ... as date)
并进行转换:
cast(DateReceived date) = @startdate
对于等于DateReceived between @startdate at 00:00 but before the next day at 00:00
的范围查询,允许其使用DateReceived
上的任何索引