Функция Floor() для даты и времени - SQL Server
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, он не вернет заказ, который был размещен в 12:00:00 утра 07-20-18.
Так что я решил добавить>= к предложению
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 ответ
Вместо того, чтобы использовать 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 для типов datetime. Двузначные годы просто умоляют о неверной интерпретации пути.
cast(DateReceived date)
преобразует datetime
значения в DateReceived
в date
ценности. Обычно плохая идея применять функции к полям, потому что это не позволяет оптимизатору запросов использовать какие-либо индексы. SQL Server понимает cast( ... as date)
хотя и конвертирует
cast(DateReceived date) = @startdate
Для запроса диапазона, эквивалентного DateReceived between @startdate at 00:00 but before the next day at 00:00
, позволяя использовать любые индексы на DateReceived