Truy vấn SQL để chọn ngày giữa hai ngày


303

Tôi có một start_dateend_date. Tôi muốn có được danh sách các ngày ở giữa hai ngày này. Bất cứ ai có thể giúp tôi chỉ ra lỗi trong truy vấn của tôi.

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

Đây Datelà một datetimebiến.

Câu trả lời:


484

bạn nên đặt hai ngày đó giữa các trích dẫn đơn như ..

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

hoặc có thể sử dụng

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

Hãy nhớ rằng ngày đầu tiên là bao gồm, nhưng ngày thứ hai là độc quyền, vì nó thực sự là '2011/02/27 00:00:00'


42
SQL Server mặc định một ngày không có thời gian đến 00:00:00. Vì vậy, truy vấn này sẽ không trả lại bất cứ điều gì từ 2011/02/26 và 2011/02/26 lúc nửa đêm?
Matt

5
@Deepak, bit thứ hai của bạn sẽ nói> = và <=
IndoKnight

3
Bạn có thể đề cập rằng thứ tự quan trọng trong chức năng GIỮA. Nó phải đi từ cũ nhất bên trái và gần đây hơn bên phải. Điều này là không trực quan vì = là một toán tử so sánh trong sql và hoạt động cho cả "EmployeeId = 1" hoặc "1 = EmployeeId" trong mệnh đề where.
Fi Horan

@Matt, theo tài liệu cho giữa , nếu một hàng có ngày 2011/02/27 mà không có thời gian, thì hàng đó tương đương với ngày 2011/02/27 00:00 và sẽ được trả lại trong truy vấn, bởi vì nó nhỏ hơn hoặc bằng 2011/02/27 00:00. Vì vậy, nếu bạn không giải quyết thời gian, betweennên làm việc như mong đợi.
timctran

@timctran Đúng, nhưng 2011/02/27 00:00 là những gì chúng ta sẽ gọi là nửa đêm của 2011/02/26. Có lẽ, truy vấn có nghĩa là bao gồm lần thứ 27 trong tập kết quả - nhưng một mục có dấu thời gian là 2011/02/27 5:00 sẽ không được bao gồm.
Sinjai

128

Vì một mốc thời gian không có phân đoạn thời gian xác định sẽ có giá trị date 00:00:00.000, nếu bạn muốn chắc chắn rằng bạn nhận được tất cả các ngày trong phạm vi của mình, bạn phải cung cấp thời gian cho ngày kết thúc của mình hoặc tăng ngày kết thúc và sử dụng <.

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

HOẶC LÀ

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

HOẶC LÀ

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

KHÔNG sử dụng như sau, vì nó có thể trả về một số hồ sơ từ 2011/02/11 nếu thời gian của chúng là 00: 00: 00.000.

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

42
Mọi người vẫn nhìn vào những câu hỏi và câu trả lời này, ngay cả khi ban đầu chúng được đặt ra một thời gian. Tôi đã tìm kiếm một câu trả lời, và phần lớn những gì tôi thấy ở đây là không đầy đủ hoặc hoàn toàn không chính xác. Câu trả lời của tôi sẽ không giúp ích cho poster gốc, nhưng nó có thể giúp được ai đó, thậm chí là ba năm nữa.
WelshDragon

3
Câu trả lời của bạn đã giúp tôi rất nhiều, @WelshDragon - Các câu trả lời khác bỏ qua thực tế là định dạng ngày cần phải là "ngày đơn giản" trên máy chủ để bỏ qua giờ. "<= END_DATE" giả sử 12AM, điều mà tôi không biết. Tôi đã thực hiện một truy vấn với "... <= 01/01/2014" và tôi không thể hiểu tại sao các đơn đặt hàng vào ngày đó không hiển thị cho lần đầu tiên. Cảm ơn rât nhiều.
Keith

@WelshDragon - câu trả lời của bạn là một tài liệu rất tốt để sử dụng ngày làm mệnh đề where. Cảm ơn bạn
Jack Frost

Có gì sai nếu nó trở lại '2011/02/28 00:00:00.000'?
Muflix

1
Đã thử điều này ngày hôm nay, bạn cũng có thể sử dụng convert(date, Date) between '2011/02/25' and '2011/02/27'(ít nhất là với MS SQL Server gần đây). Phần convert()sẽ đảm nhiệm tước phần thời gian và phần so sánh sau đó sẽ hoạt động như mong đợi.
Sensei

14

Thử cái này:

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

Các giá trị ngày cần được gõ dưới dạng chuỗi.

Để đảm bảo bằng chứng trong tương lai, truy vấn của bạn cho SQL Server 2008 trở lên, Datenên được thoát vì đó là một từ dành riêng trong các phiên bản sau.

Hãy nhớ rằng những ngày không có thời gian mất nửa đêm là mặc định của chúng, vì vậy bạn có thể không có giá trị chính xác ở đó.


1
Ngày không phải là một từ khóa và không cần phải thoát. Làm nổi bật cú pháp chỉ là tô sáng cú pháp, từ khóa chỉ cần thoát nếu chúng gây ra lỗi cú pháp. Đó cũng là một cách thực hành tốt để sử dụng chuyển đổi rõ ràng thay vì chuyển đổi ngầm định các hằng số dữ liệu. - và Ngày giữa CAST ('2011/02 / 25'AS DATETIME) và CAST (' 2011/02 / 27'AS DATETIME)
tponthieux

5
Đương nhiên, bạn đúng nếu đây là SQL Server 2005, được OP gắn thẻ. Tuy nhiên, Date được bảo lưu trong năm 2008 trở lên, vì vậy để chứng minh trong tương lai, không có hại gì trong việc thoát khỏi nó. Tôi đã chỉnh sửa câu trả lời của mình.

1
Nếu anh ta chỉ định ngày duy nhất cho cả hai thì nó sẽ trả về hàng 0 nhưng tôi đoán đó không phải là yêu cầu của op
Zo Has

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

Ở đây, trước tiên hãy thêm một ngày vào endDate hiện tại 2011-02-28 00:00:00, sau đó bạn sẽ trừ đi một giây để tạo ngày kết thúc 2011-02-27 23:59:59. Bằng cách này, bạn có thể nhận được tất cả các ngày giữa các khoảng thời gian nhất định.

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'

- nếu loại dữ liệu khác nhau


5

Truy vấn này phù hợp để tìm nạp các giá trị giữa ngày hiện tại và 3 ngày tiếp theo của nó

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

Điều này cuối cùng sẽ thêm 3 ngày đệm cho ngày hiện tại.


5

Điều này rất lâu đời, nhưng với rất nhiều kinh nghiệm tôi đã có với ngày, bạn có thể muốn xem xét điều này: Mọi người sử dụng các cài đặt khu vực khác nhau, như vậy, một số người (và một số cơ sở dữ liệu / máy tính, tùy thuộc vào cài đặt khu vực) có thể đọc điều này ngày 11/12/2016 là ngày 11 tháng 12 năm 2016 hoặc ngày 12 tháng 11 năm 2016. Thậm chí, ngày 16/11/12 được cung cấp cho cơ sở dữ liệu MySQL sẽ được chuyển đổi nội bộ sang ngày 12 tháng 11 năm 2016, trong khi cơ sở dữ liệu Access chạy trên máy tính cài đặt khu vực ở Anh sẽ diễn giải và lưu trữ vào ngày 16 tháng 11 năm 2012.

Do đó, tôi đã biến chính sách của mình thành rõ ràng bất cứ khi nào tôi sẽ tương tác với ngày và cơ sở dữ liệu. Vì vậy, tôi luôn cung cấp các truy vấn và mã lập trình của mình như sau:

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

Cũng lưu ý rằng Access sẽ chấp nhận #, do đó:

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

nhưng máy chủ MS SQL sẽ không, vì vậy tôi luôn sử dụng "'" như trên, cả hai cơ sở dữ liệu đều chấp nhận.

Và khi nhận được ngày đó từ một biến trong mã, tôi luôn chuyển đổi kết quả thành chuỗi như sau:

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

Tôi viết thư này vì tôi biết đôi khi một số lập trình viên có thể không đủ nhạy bén để phát hiện chuyển đổi vốn có. Sẽ không có lỗi cho ngày <13, chỉ là kết quả khác nhau!

Đối với câu hỏi được hỏi, thêm một ngày vào ngày cuối cùng và thực hiện so sánh như sau:

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

thông tin của bạn đã giúp hoàn thành nhiệm vụ của tôi. tôi đã làm việc này hơn 10 giờ và không có câu trả lời nào phù hợp với tôi. Khi tôi kết nối như bạn đã cho thấy dự án của tôi hoạt động tuyệt vời. nhưng quy tắc dường như là không viết một câu lệnh SQL như thế này. Khi tôi cố gắng thiết lập SqlCommand để thêm các tham số ngày vào câu lệnh SQL, các tham số sẽ không đính kèm và tôi nhận được lỗi rằng tôi phải khai báo "@startDate" và "@endDate". tôi không thể vượt qua vấn đề này Tôi đã thử định dạng ngày của bạn "dd MMM yyyy" đã hoạt động và tôi cũng đã thử "yyyy MMM dd" cũng hoạt động tương tự.
Dave Hampel

Tuyệt vời nó đã giúp! Trên đây là các mẫu mã. Luôn luôn tốt hơn để khai báo và sử dụng các tham số để tránh SQL Injection. Và có vẻ như bạn đã được yêu cầu / bảo vệ bởi các quy tắc trong dự án của bạn, điều này là tốt.
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

Hãy thử đặt ngày giữa # # chẳng hạn:

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

Nó làm việc cho tôi.


1
# Làm gì trong bối cảnh này?
BK

@BK nó là một dấu phân cách, giống như dấu ngoặc kép cho chuỗi. "Khi cung cấp giá trị cho câu lệnh SQL, ví dụ như tiêu chí truy vấn, loại dữ liệu của chúng phải được xác định chính xác bởi" vòng loại ". ​​Điều này được thực hiện bằng cách đặt giá trị giữa một cặp ký tự phù hợp." tham khảo -> liên kết
Aleksandar

1
@BK Nếu đó là cú pháp TSql, Bạn sẽ cần sử dụng dấu ngoặc kép đơn ( ' ) để có được thứ bạn cần. tài liệu tham khảo * những điều cơ bản của sql-font ware.com * Bắt đầu SQL - Paul Wilton, John Colby
Aleksandar

1
Không thể rõ ràng hơn rằng câu hỏi dành cho SQL Server và T-SQL. T-SQL và SQL Server không chấp nhận ngày giữa các thẻ băm, nó chấp nhận ngày giữa các dấu ngoặc đơn. Câu trả lời này là sai.
TT.

@TT. số lượng upvote nói rằng nó vẫn giúp được ai đó. Tại thời điểm tôi viết câu trả lời của mình, câu trả lời được chấp nhận đã được chọn. Tuy nhiên, tôi đã viết thư này để giúp bất kỳ ai có thể đến đây từ Google hoặc ở nơi khác :)
Aleksandar

2

Nếu ngày của nó trong 24 giờ và bắt đầu vào buổi sáng và kết thúc vào ban đêm thì nên thêm một cái gì đó như:

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

truy vấn tốt nhất cho ngày chọn giữa ngày hiện tại và trở lại ba ngày :

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

truy vấn tốt nhất cho ngày chọn giữa ngày hiện tại và ba ngày tiếp theo :

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

1

Kiểm tra các ví dụ dưới đây: Cả làm việc và không làm việc.

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

HOẶC LÀ

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

HOẶC LÀ

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

VÀ bên dưới không hoạt động:

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

chúng ta có thể sử dụng giữa để hiển thị hai dữ liệu ngày nhưng điều này sẽ tìm kiếm toàn bộ dữ liệu và so sánh để nó làm cho quá trình của chúng ta bị chậm đối với dữ liệu lớn, vì vậy tôi khuyên mọi người nên sử dụng datediff:

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

ở đây lịch là Bảng, dt là biến ngày bắt đầu và dt2 là biến ngày kết thúc.


0

Tôi thích sử dụng cú pháp '1 MonthName 2015' cho ngày cũ:

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

cho ngày


0

Tôi sẽ đi cho

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

Logic >=bao gồm toàn bộ ngày bắt đầu và <không bao gồm ngày kết thúc, vì vậy chúng tôi thêm một đơn vị vào ngày kết thúc. Điều này có thể thích nghi trong nhiều tháng, ví dụ:

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

Bạn hãy thử SQL này

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

tốt hơn nên viết theo cách này:

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
Sử dụng một thủ tục lưu trữ trong tình huống này sẽ không có ý nghĩa gì vì nó sẽ làm giảm đáng kể tính linh hoạt của truy vấn SQL, nó sẽ rất cụ thể, Nếu bạn không muốn sử dụng nó trong một tình huống thực sự cụ thể, vui lòng không sử dụng Thủ tục lưu trữ - Ngoài ra còn có nhiều cải tiến có sẵn cho Thủ tục lưu trữ mà bạn có thể tìm thấy chúng trong cộng đồng này;).
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
Có lẽ bạn đã nghĩ về Oracle SQL khi bạn viết câu trả lời này. Điều này là hợp lệ trong Oracle. Không quá nhiều trong SQL Server (từ những gì tôi có thể thấy).
Charles Caldwell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.