SQL-запрос для выбора дат между двумя датами


303

У меня есть start_dateи end_date. Я хочу получить список дат между этими двумя датами. Может ли кто-нибудь помочь мне указать ошибку в моем запросе.

select Date,TotalAllowance 
from Calculation 
where EmployeeId=1
  and Date between 2011/02/25 and 2011/02/27

Вот Dateэто datetimeпеременная.

Ответы:


484

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

select Date, TotalAllowance from Calculation where EmployeeId = 1
             and Date between '2011/02/25' and '2011/02/27'

или можно использовать

select Date, TotalAllowance from Calculation where EmployeeId = 1
             and Date >= '2011/02/25' and Date <= '2011/02/27'

имейте в виду, что первое свидание является инклюзивным, а второе - эксклюзивным, так как фактически это «2011/02/27 00:00:00».


42
SQL Server по умолчанию устанавливает дату без времени на 00:00:00. Так не будет ли этот запрос возвращать что-либо с 2011/02/25 и 2011/02/26 в полночь?
Мэтт

5
@Deepak, ваш второй бит должен сказать> = и <=
IndoKnight

3
Вы могли бы упомянуть, что порядок имеет значение в функции МЕЖДУ. Это должно идти от самого старого слева и более нового справа. Это не интуитивно понятно, так как = является сравнительным оператором в SQL и работает как для «EmployeeId = 1», так и для «1 = EmployeeId» в предложении where.
Fi Horan

@Matt, в соответствии с документацией на промежуток времени , если в строке была дата 2011/02/27 без времени, то эта строка эквивалентна дате 2011/02/27 00:00 и будет возвращена в запрос, потому что он меньше или равен 2011/02/27 00:00. Так что, если вы не имеете дело со временем, betweenдолжны работать как положено.
тимктран

@timctran Правильно, но 2011/02/27 00:00 - это то, что мы назвали бы полуночью 2011/02/26. Предположительно, запрос означает включение 27-го числа в набор результатов, но запись с отметкой времени 2011/02/27 5:00 не будет включена.
Синджай,

128

Поскольку у даты и времени без указанного временного сегмента будет значение date 00:00:00.000, если вы хотите быть уверенным, что вы получаете все даты в своем диапазоне, вы должны либо указать время для даты окончания, либо увеличить дату окончания и использовать <.

select Date,TotalAllowance from Calculation where EmployeeId=1 
and Date between '2011/02/25' and '2011/02/27 23:59:59.999'

ИЛИ

select Date,TotalAllowance from Calculation where EmployeeId=1 
and Date >= '2011/02/25' and Date < '2011/02/28'

ИЛИ

select Date,TotalAllowance from Calculation where EmployeeId=1 
and Date >= '2011/02/25' and Date <= '2011/02/27 23:59:59.999'

НЕ ИСПОЛЬЗУЙТЕ следующее, так как это может вернуть некоторые записи с 2011/02/28, если их время - 00: 00: 00.000.

select Date,TotalAllowance from Calculation where EmployeeId=1 
and Date between '2011/02/25' and '2011/02/28'

42
Люди все еще смотрят на эти вопросы и ответы, даже если они были заданы некоторое время назад. Я пришел в поисках ответа, и многое из того, что я увидел, было неполным или абсолютно неправильным. Мой ответ не поможет оригинальному постеру, но может кому-то помочь, возможно, даже через три года.
WelshDragon

3
Ваш ответ мне очень помог, @WelshDragon - другие ответы не учитывают тот факт, что формат даты должен быть «простой датой» на сервере, чтобы игнорировать часы. «<= END_DATE» предполагает 12:00, что я не знал. Я выполнял запрос с "... <= 01/01/2014" и не мог понять, почему заказы в эту дату не показывались для 1-го числа. Большое спасибо.
Кит

@WelshDragon - ваш ответ - очень хороший материал для использования даты в качестве условия where. Спасибо
Джек Фрост,

что не так, если он вернется '2011/02/28 00:00:00.000'?
Muflix

1
Пробовал сегодня, вы также можете использовать convert(date, Date) between '2011/02/25' and '2011/02/27'(по крайней мере, с недавним MS SQL Server). Эта convert()часть позаботится об удалении части времени, и тогда сравнение между ними будет работать, как и ожидалось.
сэнсэй

14

Попробуй это:

select Date,TotalAllowance from Calculation where EmployeeId=1
             and [Date] between '2011/02/25' and '2011/02/27'

Значения даты должны быть напечатаны в виде строк.

Чтобы обеспечить защиту вашего запроса для SQL Server 2008 и более Dateпоздних версий , его следует экранировать, поскольку в более поздних версиях это зарезервированное слово.

Имейте в виду, что по умолчанию для дат без времени принимается полночь, поэтому у вас там может быть неправильное значение.


1
Дата не является ключевым словом и не требует экранирования. Подсветка синтаксиса - это просто подсветка синтаксиса, ключевые слова необходимо экранировать, только если они вызывают синтаксическую ошибку. Также рекомендуется использовать явное преобразование вместо неявного преобразования констант строки даты. - и Дата между CAST ('2011/02 / 25'AS DATETIME) и CAST (' 2011/02 / 27'AS DATETIME)
tponthieux

5
Естественно, вы правы, если это SQL Server 2005, помеченный OP. Тем не менее, Дата зарезервирована в 2008 году и выше, так что для будущего не избежать вреда. Я отредактировал свой ответ.

1
Если бы он указал одну и ту же дату для обоих, он бы возвратил ноль строк, но я думаю, что это не требование оп
Zo Has

12
select * from table_name where col_Date between '2011/02/25' 
AND DATEADD(s,-1,DATEADD(d,1,'2011/02/27'))

Здесь сначала добавьте день к текущей конечной дате, это будет 2011-02-28 00:00:00, а затем вычтите одну секунду, чтобы сделать конечную дату 2011-02-27 23:59:59. Делая это, вы можете получить все даты между заданными интервалами.

output:
2011/02/25
2011/02/26
2011/02/27

8
select * from test 
     where CAST(AddTime as datetime) between '2013/4/4' and '2014/4/4'

- если тип данных отличается


5

Этот запрос подходит для извлечения значений между текущей датой и ее следующими 3 датами.

SELECT * FROM tableName  WHERE columName 
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 3 DAY)

Это в конечном итоге добавит дополнительные 3 дня буфера к текущей дате.


5

Это очень старый процесс, но учитывая большой опыт, который я имел с датами, вы можете подумать об этом: люди используют разные региональные настройки, поэтому некоторые люди (и некоторые базы данных / компьютеры, в зависимости от региональных настроек) могут читать это дата 11/12/2016 - 11 декабря 2016 года или 12 ноября 2016 года. Более того, 16/11/12, поставляемая в базу данных MySQL, будет внутренне преобразована в 12 ноября 2016 года, а база данных Access, работающая на компьютере с региональными настройками в Великобритании, будет интерпретировать и хранить его как 16 ноября 2012 года.

Поэтому я решил, что моя политика должна быть явной, когда я собираюсь взаимодействовать с датами и базами данных. Поэтому я всегда предоставляю свои запросы и программные коды следующим образом:

SELECT FirstName FROM Students WHERE DoB >= '11 Dec 2016';

Также обратите внимание, что Access примет #, таким образом:

SELECT FirstName FROM Students WHERE DoB >= #11 Dec 2016#;

но MS SQL server не будет, поэтому я всегда использую «», как указано выше, что принимают обе базы данных.

И когда я получаю эту дату из переменной в коде, я всегда конвертирую результат в строку следующим образом:

"SELECT FirstName FROM Students WHERE DoB >= " & myDate.ToString("d MMM yyyy")

Я пишу это, потому что я знаю, что иногда некоторые программисты могут быть недостаточно заинтересованы в обнаружении собственного преобразования. Для дат <13 ошибок не будет, просто разные результаты!

Что касается заданного вопроса, добавьте один день к последней дате и сделайте сравнение следующим образом:

dated >= '11 Nov 2016' AND dated < '15 Nov 2016' 

Ваша информация помогла выполнить мою задачу. Я работал над этим более 10 часов, и ни один из ответов не сработал бы для меня. Когда я конкатенирую, как вы показали, мой проект работает отлично. но, похоже, правило не должно писать оператор SQL, подобный этому. всякий раз, когда я пытаюсь установить SqlCommand для добавления параметров даты в оператор SQL, параметры не будут прикреплены, и я получаю ошибку, которую я должен объявить "@startDate" и "@endDate". я не могу пройти мимо этого вопроса. Я попробовал ваш формат даты "dd MMM yyyy", который работал, и я также попробовал "yyyy MMM dd", который также выполнил то же самое.
Дейв Хэмпел

Здорово это помогло! Выше приведены примеры кода. Всегда лучше объявлять и использовать параметры, чтобы избежать SQL-инъекций. И кажется, что вы уже обязаны / защищены правилами в вашем проекте, и это хорошо.
Ханнингтон Мамбо

4
select Date,TotalAllowance 
from Calculation 
where EmployeeId=1
  and convert(varchar(10),Date,111) between '2011/02/25' and '2011/02/27'

3

Попробуйте поставить даты между # #, например:

#2013/4/4# and #2013/4/20#

Это сработало для меня.


1
Что # делает в этом контексте?
БК

@BK это разделитель, как кавычки для строк. «При предоставлении значений в оператор SQL, например, в качестве критериев запроса, их тип данных должен быть правильно определен с помощью« квалификатора ». Это делается путем помещения значения между парой соответствующих символов». ссылка -> ссылка
Александр

1
@BK Если это синтаксис TSql, вам нужно будет использовать одинарные кавычки ( ' ), чтобы получить то, что вам нужно. ссылки * основы sql-fontstuff.com * Начало SQL - Пол Уилтон, Джон Колби
Александар

1
Не может быть более ясным, что вопрос касается SQL Server и T-SQL. T-SQL и SQL Server не принимают даты между хеш-тегами, он принимает даты между одинарными кавычками. Этот ответ неверен.
ТТ.

@TT. количество голосов говорит, что это все еще помогло кому-то. Когда я написал свой ответ, принятый ответ уже был выбран. Тем не менее, я написал это, чтобы помочь любому, кто может прийти сюда из Google или из другого места :)
Александар

2

если его дата в 24 часа и начинается утром и заканчивается ночью, следует добавить что-то вроде:

declare @Approval_date datetime
set @Approval_date =getdate()
Approval_date between @Approval_date +' 00:00:00.000' and @Approval_date +' 23:59:59.999'

1

лучший запрос для выбранной даты между текущей датой и тремя днями назад :

  select Date,TotalAllowance from Calculation where EmployeeId=1 and Date BETWEEN       
DATE_SUB(CURDATE(), INTERVAL 3 DAY)  AND CURDATE() 

лучший запрос для выбранной даты между текущей датой и следующими тремя днями :

  select Date,TotalAllowance from Calculation where EmployeeId=1 and Date BETWEEN   
   CURDATE()  AND DATE_ADD(CURDATE(), INTERVAL 3 DAY)   

1

Проверьте ниже Примеры: как работающие, так и нерабочие.

select * from tblUser Where    
convert(varchar(10),CreatedDate,111) between '2015/04/01' and '2016/04/01' //--**Working**

ИЛИ

select * from tblUser Where
(CAST(CreatedDate AS DATETIME) between CAST('2015/04/01' AS DATETIME) And CAST('2016/4/30'AS DATETIME)) //--**Working**

ИЛИ

select * from tblUser Where
(YEAR(CreatedDate) between YEAR('2015/04/01') And YEAR('2016/4/30')) 
//--**Working**

И ниже не работает:

select * from tblUser Where
Convert(Varchar(10),CreatedDate,111) >=  Convert(Varchar(10),'01-01-2015',111) and  Convert(Varchar(10),CreatedDate,111) <= Convert(Varchar(10),'31-12-2015',111) //--**Not Working**


select * from tblUser Where
(Convert(Varchar(10),CreatedDate,111) between Convert(Varchar(10),'01-01-2015',111) And Convert(Varchar(10),'31-12-2015',111)) //--**Not Working**

1

мы можем использовать между ними, чтобы показать данные двух дат, но при этом будет выполнен поиск по всем данным и сравнение, что замедлит процесс обработки больших данных, поэтому я предлагаю всем использовать datediff:

qry = "SELECT * FROM [calender] WHERE datediff(day,'" & dt & "',[date])>=0 and datediff(day,'" & dt2 & "',[date])<=0 "

здесь calender - таблица, dt - переменная даты начала, а dt2 - переменная даты окончания.


0

Мне нравится использовать синтаксис «1 MonthName 2015» для дат, например:

   WHERE aa.AuditDate>='1 September 2015'
     AND aa.AuditDate<='30 September 2015'

для свиданий


0

Я бы пошел на

select Date,TotalAllowance from Calculation where EmployeeId=1
             and Date >= '2011/02/25' and Date < DATEADD(d, 1, '2011/02/27')

Логика заключается в том, что >=включает в себя всю дату начала и <исключает дату окончания, поэтому мы добавляем одну единицу к дате окончания. Это может быть адаптировано для месяцев, например:

select Date, ... from ...
             where Date >= $start_month_day_1 and Date < DATEADD(m, 1, $end_month_day_1)


0

Вы можете попробовать этот SQL

select * from employee where rec_date between '2017-09-01' and '2017-09-11' 


0
/****** Script for SelectTopNRows command from SSMS  ******/
SELECT TOP 10 [Id]
  ,[Id_parvandeh]
  ,[FirstName]
  ,[LastName]
  ,[RegDate]
  ,[Gilder]
  ,[Nationality]
  ,[Educ]
  ,[PhoneNumber]
  ,[DueInMashhad]

  ,[EzdevajDate]


  ,[MarriageStatus]
  ,[Gender]
  ,[Photo]

  ,[ModifiedOn]
  ,[CreatorIp]
   From
  [dbo].[Socials] where educ >= 3 or EzdevajDate  >= '1992/03/31' and EzdevajDate <= '2019/03/09' and MarriageStatus = 1

-2

лучше написать так:

CREATE PROCEDURE dbo.Get_Data_By_Dates
(
    @EmployeeId INT = 1,
    @Start_Date DATE,
    @End_Date Date
)
AS
Select * FROM Calculation  
    where EmployeeId=@EmployeeId AND Test_Date BETWEEN @Start_Date AND @End_Date
RETURN

1
Использование хранимой процедуры в этой ситуации не имеет никакого смысла, так как это ужасно снижает гибкость SQL-запроса, это будет настолько специфично. Если вы не хотите использовать его в действительно конкретной ситуации, пожалуйста, не используйте Хранимая процедура - также есть много улучшений для вашей хранимой процедуры, которые вы можете найти в этом сообществе;).
shA.t

-6
SELECT Date, TotalAllowance  
FROM Calculation  
WHERE EmployeeId = 1 
  AND Date BETWEEN to_date('2011/02/25','yyyy-mm-dd') 
               AND to_date ('2011/02/27','yyyy-mm-dd');

1
Возможно, вы думали об Oracle SQL, когда писали этот ответ. Это действительно в Oracle. Не так много в SQL Server (из того, что я вижу).
Чарльз Колдуэлл
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.