Zapytanie SQL, aby wybrać daty między dwiema datami


303

Mam start_datei end_date. Chcę uzyskać listę dat pomiędzy tymi dwiema datami. Czy ktoś może mi pomóc wskazać błąd w moim zapytaniu.

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

Oto Dateadatetime zmienna.

Odpowiedzi:


484

powinieneś umieścić te dwie daty między pojedynczymi cudzysłowami, takimi jak ...

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

lub może użyć

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

pamiętaj, że pierwsza data jest wliczona, ale druga jest wyłączna, ponieważ w rzeczywistości jest to „2011/02/27 00:00:00”


42
SQL Server domyślnie ustawia datę bez godziny na 00:00:00. Czy to zapytanie nie zwróci niczego z 2011/02/25 i 2011/02/26 o północy?
Matt

5
@Deepak, twój drugi bit powinien powiedzieć> = i <=
IndoKnight

3
Możesz wspomnieć, że kolejność ma znaczenie w funkcji MIĘDZY. Musi pochodzić od najstarszych po lewej i nowszych po prawej. Jest to nieintuicyjne, ponieważ = jest operatorem porównawczym w sql i działa zarówno dla „EmployeeId = 1”, jak i „1 = EmployeeId” w klauzuli where.
Fi Horan,

@Matt, zgodnie z dokumentacją pomiędzy , jeśli wiersz miał datę 2011/02/27 bez czasu, wówczas wiersz ten jest równoważny z datą 2011/02/27 00:00 i zostanie zwrócony w zapytanie, ponieważ jest mniejsze lub równe 2011/02/27 00:00. Więc jeśli nie masz do czynienia z czasem, betweenpowinien działać zgodnie z oczekiwaniami.
timctran

@timctran Racja, ale 2011/02/27 00:00 to, co nazwalibyśmy północą 2011/02/26. Przypuszczalnie zapytanie oznacza włączenie 27 do zestawu wyników - ale wpis z datownikiem 2011/02/27 5:00 nie zostałby uwzględniony.
Sinjai

128

Ponieważ data i godzina bez określonego odcinka czasu będzie miała wartość date 00:00:00.000, jeśli chcesz mieć pewność, że otrzymujesz wszystkie daty w swoim zakresie, musisz albo podać datę końcową, albo zwiększyć datę końcową i użyć <.

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

LUB

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

LUB

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

NIE używaj następujących danych, ponieważ mogą zwrócić niektóre rekordy z 2011/02/28, jeśli ich czasy to 00: 00: 00.000.

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

42
Ludzie wciąż patrzą na te pytania i odpowiedzi, nawet jeśli pierwotnie postawiono im trochę czasu. Przyszedłem szukać odpowiedzi i wiele z tego, co tu widziałem, było niepełne lub absolutnie niepoprawne. Moja odpowiedź nie pomoże oryginalnemu plakatowi, ale może komuś pomóc, może nawet za trzy lata.
WelshDragon

3
Twoja odpowiedź bardzo mi pomogła, @WelshDragon - Inne odpowiedzi pominęły fakt, że format daty musi być „prostą datą” na serwerze, aby zignorować godziny. „<= END_DATE” zakłada godzinę 12:00, której nie znałem. Wykonałem zapytanie z „... <= 01.01.2014” i nie mogłem zrozumieć, dlaczego zamówienia z tego dnia nie były wyświetlane dla pierwszego. Dziękuję Ci bardzo.
Keith

@WelshDragon - twoja odpowiedź jest bardzo dobrym materiałem do używania dat jako klauzuli where. Dziękuję
Jack Frost

co jest nie tak, jeśli wróci '2011/02/28 00:00:00.000'?
Muflix,

1
Próbowałem tego dzisiaj, możesz również użyć convert(date, Date) between '2011/02/25' and '2011/02/27'(przynajmniej z najnowszym MS SQL Server). convert()Część zajmie stripping część czasu i pomiędzy porównaniu wtedy działać zgodnie z oczekiwaniami.
sensei

14

Spróbuj tego:

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

Wartości daty należy wpisać jako ciągi.

Aby upewnić się, że Twoje zapytanie na SQL Server 2008 i nowsze jest zabezpieczone na przyszłość, Datenależy je zmienić, ponieważ jest to słowo zastrzeżone w późniejszych wersjach.

Pamiętaj, że daty bez czasu przyjmują domyślnie północ, więc możesz nie mieć tam prawidłowej wartości.


1
Data nie jest słowem kluczowym i nie wymaga zmiany znaczenia. Podświetlanie składni jest po prostu podświetlaniem składni, słowa kluczowe muszą być poprzedzane znakami ucieczki, jeśli powodują błąd składniowy. Dobrą praktyką jest również stosowanie jawnej konwersji zamiast niejawnej konwersji stałych danych. - i data między CAST ('2011/02 / 25'AS DATETIME) i CAST (' 2011/02 / 27'AS DATETIME)
tponthieux

5
Oczywiście masz rację, jeśli jest to SQL Server 2005, który OP oznaczył. Data jest jednak zarezerwowana w 2008 r. I później, więc dla zabezpieczenia na przyszłość ucieczka przed nią nie zaszkodzi. Zredagowałem swoją odpowiedź.

1
Jeśli określiłby pojedynczą datę dla obu, zwróciłoby zero wierszy, ale myślę, że nie jest to wymóg
operacyjny

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

Tutaj najpierw dodaj dzień do bieżącej daty końcowej 2011-02-28 00:00:00, a następnie odejmij jedną sekundę, aby ustawić datę końcową 2011-02-27 23:59:59. W ten sposób możesz uzyskać wszystkie daty między podanymi interwałami.

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'

- jeśli typ danych jest inny


5

To zapytanie jest przydatne do pobierania wartości między bieżącą datą a następnymi 3 datami

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

To ostatecznie doda dodatkowe 3 dni bufora do bieżącej daty.


5

To jest bardzo stare, ale biorąc pod uwagę wiele doświadczeń, które miałem z datami, możesz rozważyć to: Ludzie używają różnych ustawień regionalnych, jako takie, niektóre osoby (i niektóre bazy danych / komputery, w zależności od ustawień regionalnych) mogą to przeczytać data 11.12.2016 jako 11 grudnia 2016 r. lub 12 listopada 2016 r. Co więcej, 16.11.12 dostarczony do bazy danych MySQL zostanie wewnętrznie przekonwertowany na 12 listopada 2016 r., natomiast baza danych Access działająca na komputerze regionalnym w Wielkiej Brytanii zinterpretuje i zapisz jako 16 listopada 2012.

Dlatego postanowiłem, że moje zasady będą jawne za każdym razem, gdy będę wchodzić w interakcje z datami i bazami danych. Dlatego zawsze dostarczam moje zapytania i kody programowania w następujący sposób:

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

Pamiętaj również, że Access zaakceptuje #, a zatem:

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

ale serwer MS SQL nie będzie, więc zawsze używam „” jak wyżej, co akceptują obie bazy danych.

A kiedy otrzymuję tę datę ze zmiennej w kodzie, zawsze przekształcam wynik na ciąg znaków w następujący sposób:

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

Piszę to, ponieważ wiem, że niektórzy programiści mogą nie być wystarczająco chętni, aby wykryć nieodłączną konwersję. Nie będzie błędu dla dat <13, tylko inne wyniki!

Jeśli chodzi o zadane pytanie, dodaj jeden dzień do ostatniej daty i wykonaj porównanie w następujący sposób:

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

Twoje informacje pomogły mi ukończyć moje zadanie. pracowałem nad tym przez ponad 10 godzin i żadna z odpowiedzi nie zadziałałaby dla mnie. Kiedy konkatenuję, jak pokazałeś, mój projekt działa świetnie. ale regułą wydaje się nie pisać takiej instrukcji SQL. Kiedykolwiek próbuję ustawić SqlCommand na dodanie parametrów daty do instrukcji SQL, parametry nie zostaną dołączone i pojawia się błąd, że muszę zadeklarować „@startDate” i „@endDate”. nie mogę przejść tego problemu. Próbowałem formatu daty „dd MMM rrrr”, który zadziałał, a także spróbowałem „rrrr MMM dd”, który również działał tak samo.
Dave Hampel

Świetnie, pomogło! Powyżej znajdują się próbki kodu. Zawsze lepiej jest zadeklarować i użyć parametrów, aby uniknąć wstrzyknięcia SQL. I wygląda na to, że jesteś już wymagany / chroniony przez zasady w swoim projekcie, co jest dobre.
Hannington Mambo

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

3

Spróbuj umieścić daty między # # na przykład:

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

To zadziałało dla mnie.


1
Co robi # w tym kontekście?
BK

@BK jest to separator, podobnie jak znaki cudzysłowu dla ciągów. „Przy podawaniu wartości do instrukcji SQL, na przykład jako kryteriów zapytania, ich typ danych musi być poprawnie zdefiniowany przez„ kwalifikator ”. Odbywa się to poprzez umieszczenie wartości między parą odpowiednich znaków.” odniesienie -> link
Aleksandar

1
@BK Jeśli jest to składnia TSql, musisz użyć pojedynczych cudzysłowów ( ' ), aby uzyskać to, czego potrzebujesz. referencje * podstawy sql-fontstuff.com * Począwszy od SQL - Paul Wilton, John Colby
Aleksandar

1
Nie może być bardziej jasne, że pytanie dotyczy SQL Server i T-SQL. T-SQL i SQL Server nie akceptują dat między hashami, akceptuje daty między pojedynczymi cudzysłowami. Ta odpowiedź jest zła.
TT.

@TT. liczba entuzjastów mówi, że nadal komuś to pomogło. Kiedy pisałem odpowiedź, zaakceptowana odpowiedź była już wybrana. Mimo to napisałem to, aby pomóc każdemu, kto może przyjść tutaj z Google lub gdzie indziej :)
Aleksandar

2

jeśli jego data przypada za 24 godziny i zaczyna się rano, a kończy w nocy, należy dodać coś takiego:

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

najlepsze zapytanie dla wybranej daty między bieżącą datą a poprzednimi trzema dniami :

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

najlepsze zapytanie dla wybranej daty między bieżącą datą a następnymi trzema dniami :

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

1

Sprawdź poniżej Przykłady: zarówno pracujące, jak i niedziałające.

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

LUB

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

LUB

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

ORAZ poniżej nie działa:

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

możemy użyć między, aby wyświetlić dane z dwóch dat, ale przeszuka to całe dane i porówna, dzięki czemu nasz proces będzie spowolniony w przypadku dużych danych, więc sugeruję wszystkim, aby używali datediff:

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

tutaj kalendarz to Tabela, dt jako zmienna daty początkowej, a dt2 to zmienna daty końcowej.


0

Lubię używać składni „1 MonthName 2015” dla dat, np .:

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

dla dat


0

Wybrałbym

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

Logika >=obejmuje całą datę początkową i <wyklucza datę końcową, dlatego dodajemy jedną jednostkę do daty końcowej. Można to dostosować na miesiące, na przykład:

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

0
Select 
    * 
from 
    Calculation 
where 
    EmployeeId=1 and Date between #2011/02/25# and #2011/02/27#;

0

Możesz spróbować tego 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

lepiej napisz w ten sposób:

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
Użycie procedury składowanej w tej sytuacji nie będzie miało sensu, ponieważ strasznie zmniejszy elastyczność zapytania SQL, będzie tak specyficzne, że jeśli nie chcesz go używać w naprawdę konkretnej sytuacji, nie używaj Procedura składowana - Istnieje również wiele ulepszeń dla procedury składowanej, które można znaleźć w tej społeczności;).
shA.t 10.09.17

-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
Prawdopodobnie myślałeś o Oracle SQL, kiedy pisałeś tę odpowiedź. Dotyczy to Oracle. Nie tak bardzo w SQL Server (z tego co widzę).
Charles Caldwell
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.