Дата и час в клаузата where

Как мога да избера 12/20/2008 в клауза where на sql?

Сървърът е SQL server 2005.

select * from tblErrorLog
where errorDate = '12/20/2008'

person Novice Developer    schedule 22.12.2009    source източник
comment
Какъв тип данни е колоната errorDate?   -  person OMG Ponies    schedule 22.12.2009
comment
Кодът по-горе трябва да работи, ако типът данни на колоната наистина е дата и час.   -  person ryanulit    schedule 22.12.2009
comment
Кодът по-горе няма да работи, ако форматът на датата на SQL Server не е зададен на US. Използвайте метода {ts} по-долу за независимост от локала.   -  person J__    schedule 22.12.2009
comment
По-безопасно е да конвертирате вашата дата и да посочите изрично нейния формат/тип, тъй като някои системи и код ще четат датите по различен начин.   -  person Middletone    schedule 22.12.2009


Отговори (5)


На първо място, бих препоръчал да използвате стандартния формат ISO-8601 за дата/час - той работи независимо от езиковите и регионалните настройки на вашия SQL Server. ISO-8601 е форматът YYYYMMDD - без интервали, без тирета - само данните:

select * from tblErrorLog
where errorDate = '20081220'

Второ, трябва да сте наясно, че SQL Server 2005 DATETIME винаги включва време. Ако проверите за точно съвпадение само с частта с датата, ще получите само редове, които съвпадат с време 0:00:00 - нищо друго.

Можете или да използвате която и да е от споменатите заявки за препоръчителен диапазон, или в SQL Server 2008 можете да използвате само DATE дата и час - или можете да направите проверка нещо като:

select * from tblErrorLog
where DAY(errorDate) = 20 AND MONTH(errorDate) = 12 AND YEAR(errorDate) = 2008

Което работи най-добре за вас.

Ако трябва да правите тази заявка често, можете или да опитате да нормализирате DATETIME, за да включва само датата, или можете да добавите изчислени колони за DAY, MONTH и YEAR:

ALTER TABLE tblErrorLog
   ADD ErrorDay AS DAY(ErrorDate) PERSISTED
ALTER TABLE tblErrorLog
   ADD ErrorMonth AS MONTH(ErrorDate) PERSISTED
ALTER TABLE tblErrorLog
   ADD ErrorYear AS YEAR(ErrorDate) PERSISTED

и тогава можете да зададете заявка по-лесно:

select * from tblErrorLog
where ErrorMonth = 5 AND ErrorYear = 2009

и т.н. Тъй като тези полета са изчислени и ПОСТОЯННИ, те винаги са актуални и винаги актуални, и тъй като се запазват, можете дори да ги индексирате, ако е необходимо.

person marc_s    schedule 22.12.2009
comment
след повече от 10 години отговорът ми помага толкова много. Благодаря ти!!! - person Mauricio Crispim; 01.04.2020

Не казвате коя база данни използвате, но в MS SQL Server ще бъде

WHERE DateField = {d '2008-12-20'}

Ако това е поле за клеймо за време, тогава ще ви трябва диапазон:

WHERE DateField BETWEEN {ts '2008-12-20 00:00:00'} AND {ts '2008-12-20 23:59:59'}
person J__    schedule 22.12.2009
comment
Не работи, както е описано/изисквано в MS SQL Server 2005, току-що го пробвах. Изненадващо е валиден, просто ви дава резултати, където датата е както по-горе, а часът е 00:00:00 - person Meff; 22.12.2009
comment
Благодаря, първоначалният въпрос изглеждаше така, сякаш беше просто поле за дата без време. Добавихте диапазон за полета за дата и час. - person J__; 22.12.2009
comment
@Meff Този синтаксис работи за всяка база данни, която поддържа ODBC скаларни функции, не само за MS SQL. Въпреки това всичко, което прави, е преобразуване на типа на константата от низ към дата. - person Keith; 11.03.2013

Ако приемем, че говорим за SQL Server DateTime

Забележка: BETWEEN включва двата края на диапазона, така че технически този модел ще бъде грешен:

errorDate BETWEEN '12/20/2008' AND '12/21/2008'

Предпочитаният от мен метод за период от време като този е:

'20081220' <= errorDate AND errordate < '20081221'

Работи с общи индекси (сканиране на диапазон, SARGable, без функции) и правилно изрязва полунощ на следващия ден, без да разчита на детайлността на времето на SQL Server (напр. 23:59:59.997)

person onupdatecascade    schedule 22.12.2009
comment
Изглежда, че имам няколко гласа против това и се чудя защо. Ако смятате, че това решение не работи, моля, обучете ме! - person onupdatecascade; 23.12.2009
comment
Е, току-що погледнах това някъде след първоначалното публикуване и отбелязах, че не включва времето, отбелязвайки също, че OP също не го включва, но вие споменавате детайлността на SQL. Гласувах против, защото и аз използвам този формат. - person htm11h; 11.10.2013

Използвайте функция за конвертиране, за да получите всички записи за определен ден.

Select * from tblErrorLog where convert(date,errorDate,101) = '12/20/2008'

Вижте CAST и CONVERT за повече информация

person Middletone    schedule 22.12.2009
comment
Това не е добър начин да го направите, защото индексите не могат да се използват, ако се използва convert за колоната - person James Z; 17.06.2015

person    schedule
comment
Това не работи, датите трябва да са '2008-20-12', ако използвате този подход. (гггг-дд-мм). Това би бил правилният формат, ако използвате идентификаторите {ts}. - person J__; 22.12.2009
comment
@_J_: Форматът yyyy-MM-dd работи при повечето обстоятелства, но не при всички. @onupdatecascade: Прав си. Актуализирах отговора си, за да използвам формат, безопасен при всички обстоятелства. - person LukeH; 23.12.2009
comment
Вместо ,997, което може да не е доказателство за бъдещето, трябва наистина да използвате datetime_column ›= '20081220' и datetime_column ‹ '20081221' -- по този начин също няма проблеми с формата на датата, YYYYMMDD работи - person James Z; 17.06.2015