Как я могу сравнить время в SQL Server? - PullRequest
57 голосов
/ 30 апреля 2009

Я пытаюсь сравнить время в поле datetime в запросе SQL, но я не знаю, правильно ли это. Я не хочу сравнивать часть даты, только часть времени.

Я делаю это:

SELECT timeEvent 
FROM tbEvents 
WHERE convert(datetime, startHour, 8) >= convert(datetime, @startHour, 8)

Это правильно?

Я спрашиваю это, потому что мне нужно знать, является ли 08:00:00 меньше или больше 07:30:00, и я не хочу сравнивать дату, только часть time .

Спасибо!

Ответы [ 16 ]

74 голосов
/ 30 апреля 2009

Ваше сравнение будет работать, но оно будет медленным, потому что даты конвертируются в строку для каждой строки. Чтобы эффективно сравнить две части времени, попробуйте:

declare @first datetime
set @first = '2009-04-30 19:47:16.123'
declare @second datetime
set @second = '2009-04-10 19:47:16.123'

select (cast(@first as float) - floor(cast(@first as float))) -
       (cast(@second as float) - floor(cast(@second as float)))
       as Difference

Длинное объяснение: дата на сервере SQL сохраняется как число с плавающей запятой. Цифры перед десятичной запятой представляют дату. Цифры после десятичной запятой представляют время.

Итак, вот пример даты:

declare @mydate datetime
set @mydate = '2009-04-30 19:47:16.123'

Давайте преобразовать его в число с плавающей точкой:

declare @myfloat float
set @myfloat = cast(@mydate as float)
select @myfloat
-- Shows 39931,8244921682

Теперь возьмите часть после цифры, то есть время:

set @myfloat = @myfloat - floor(@myfloat) 
select @myfloat
-- Shows 0,824492168212601

Преобразовать его обратно в дату и время:

declare @mytime datetime
set @mytime = convert(datetime,@myfloat)
select @mytime
-- Shows 1900-01-01 19:47:16.123

1900-01-01 - это просто «нулевая» дата; Вы можете отобразить часть времени с помощью convert, указав, например, формат 108, который является просто временем:

select convert(varchar(32),@mytime,108)
-- Shows 19:47:16

Преобразования между datetime и float довольно быстрые, потому что они в основном хранятся одинаково.

19 голосов
/ 30 апреля 2009
convert(varchar(5), thedate, 108) between @leftTime and @rightTime

Пояснение:

если у вас есть varchar(5), вы получите HH:mm

если у вас есть varchar(8), вы получите HH:mm ss

108 получает только время из даты SQL

@leftTime и @rightTime - две переменные для сравнения

11 голосов
/ 30 апреля 2009

Если вы используете SQL Server 2008, вы можете сделать это:

WHERE CONVERT(time(0), startHour) >= CONVERT(time(0), @startTime)

Вот полный тест:

DECLARE @tbEvents TABLE (
    timeEvent   int      IDENTITY,
    startHour   datetime
)

INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 0, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 1, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 2, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 3, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 4, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 5, GETDATE())

--SELECT * FROM @tbEvents

DECLARE @startTime  datetime

SET @startTime = DATEADD(mi, 65, GETDATE())

SELECT
    timeEvent,
    CONVERT(time(0), startHour)  AS 'startHour',
    CONVERT(time(0), @startTime) AS '@startTime'
FROM @tbEvents
WHERE CONVERT(time(0), startHour) >= CONVERT(time(0), @startTime)
4 голосов
/ 22 июня 2012
if (cast('2012-06-20 23:49:14.363' as time) between 
    cast('2012-06-20 23:49:14.363' as time) and 
    cast('2012-06-20 23:49:14.363' as time))
3 голосов
/ 17 декабря 2014

Просто измените дату и время конвертации, чтобы добиться цели:

SELECT timeEvent 
FROM tbEvents 
WHERE convert(time, startHour) >= convert(time, @startHour)
3 голосов
/ 02 ноября 2010

Использование float не работает.

DECLARE @t1 datetime, @t2 datetime
SELECT @t1 = '19000101 23:55:00', @t2 = '20001102 23:55:00'
SELECT CAST(@t1 as float) - floor(CAST(@t1 as float)), CAST(@t2 as float) - floor(CAST(@t2 as float))

Вы увидите, что значения не совпадают (SQL Server 2005). Я хотел использовать этот метод для проверки времени около полуночи (в полном методе более подробно), в котором я сравнивал текущее время между 23:55:00 и 00: 05: 00.

3 голосов
/ 30 апреля 2009

Одна (возможно, небольшая) проблема, которую я до сих пор замечал в решениях, заключается в том, что всем им, кажется, требуется вызов функции для обработки сравнения. Это означает, что механизм запросов должен будет выполнить полное сканирование таблицы, чтобы найти строки, которые вы ищете, и не сможет использовать индекс. Если таблица не станет особенно большой, это, вероятно, не окажет неблагоприятного воздействия (и вы можете с радостью проигнорировать этот ответ).

Если, с другой стороны, таблица может стать достаточно большой, производительность запроса может снизиться.

Я знаю, что вы заявили, что не хотите сравнивать часть даты - но есть ли фактическая дата, хранящаяся в столбце даты и времени, или вы используете ее для хранения только времени? Если последнее, вы можете использовать простой оператор сравнения, и это сократит использование ЦП и позволит обработчику запросов использовать статистику и индексы (если имеются) для оптимизации запроса.

Если, однако, столбец datetime используется для хранения даты и времени события, это, очевидно, не сработает. В этом случае, если вы можете изменить приложение и структуру таблицы, разделите дату и время на два отдельных столбца datetime или создайте индексированное представление, которое выбирает все (соответствующие) столбцы исходной таблицы, и еще один столбец, содержащий элемент времени, который вы хотите найти (используйте любой из предыдущих ответов, чтобы вычислить это) - и измените приложение, чтобы вместо этого запросить представление.

2 голосов
/ 11 февраля 2011

Вы можете создать две переменные даты и времени и установить только час даты, который вам нужно сравнить.

declare  @date1 datetime;
declare  @date2 datetime;

select   @date1 = CONVERT(varchar(20),CONVERT(datetime, '2011-02-11 08:00:00'), 114)
select   @date2 = CONVERT(varchar(20),GETDATE(), 114)

Дата будет "1900-01-01", вы можете сравнить ее

if @date1 <= @date2
   print '@date1 less then @date2'
else
   print '@date1 more then @date2'
2 голосов
/ 30 апреля 2009

Добавление к другим ответам:

Вы можете создать функцию для обрезки даты от даты и времени

CREATE FUNCTION dbo.f_trimdate (@dat datetime) RETURNS DATETIME AS BEGIN
    RETURN CONVERT(DATETIME, CONVERT(FLOAT, @dat) - CONVERT(INT, @dat))
END

Итак, это:

DECLARE @dat DATETIME
SELECT @dat = '20080201 02:25:46.000'
SELECT dbo.f_trimdate(@dat)

Вернется 1900-01-01 02: 25: 46.000

2 голосов
/ 30 апреля 2009

Использовать функцию Datepart: DATEPART (datepart, date)

# * например 1005 *

ВЫБРАТЬ DatePart (@YourVar, чч) * 60) + DatePart (@YourVar, mi) * 60)

Это даст вам общее время суток в минутах, что позволит вам легче сравнивать.

Вы можете использовать DateDiff, если ваши даты будут одинаковыми, в противном случае вам нужно будет удалить дату, как указано выше

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...