Câu hỏi Cách chỉ trả về Date từ kiểu dữ liệu DateTime của SQL Server


SELECT GETDATE()

Trả về: 2008-09-22 15:24:13.790

Tôi muốn phần ngày đó không có phần thời gian: 2008-09-22 00:00:00.000

Làm thế nào tôi có thể nhận được điều đó?


1409
2017-09-22 03:31


gốc


Nếu bạn đang tìm kiếm để có được một datatype ngày mà không có thời gian, ngay cả khi thời gian là 00:00:00 sau đó bạn đang trong may mắn, bạn có thể nhận được một varchar nhưng cấu trúc là một datetime và bạn sẽ luôn luôn có một thời gian. - Quintin Robinson
Một điều cần lưu ý là SQL Server 2008 bao gồm một kiểu dữ liệu DATE riêng biệt để lưu trữ các ngày tháng không có thành phần thời gian. Thông tin thêm tại đây: sql-server-performance.com/articles/dev/datetime_2008_p1.aspx - Ben Hoffstein
Đừng bỏ lỡ bài này hiển thị kết quả kiểm tra hiệu suất của các phương pháp loại bỏ thời gian khác nhau. - ErikE
Đừng bị đánh lừa bởi các phiếu bầu và câu trả lời được chấp nhận, hãy xem stackoverflow.com/a/126984/1155650 - Rohit Vipin Mathews
@Rohit Bạn đang giả định không chính xác rằng năm 2008 là phiên bản duy nhất mọi người quan tâm. (Có nhiều phiên bản trong tự nhiên.) Các lá phiếu nói cho chính họ. - hktegner


Các câu trả lời:


Trên SQL Server 2008 và cao hơn, bạn nên CONVERT cho đến nay:

SELECT CONVERT(date, getdate())

Trên các phiên bản cũ hơn, bạn có thể thực hiện các thao tác sau:

SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, @your_date))

ví dụ

SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))

đưa cho tôi

2008-09-22 00:00:00.000

Ưu điểm:

  • Không varchar<->datetime yêu cầu chuyển đổi
  • Không cần phải suy nghĩ về locale

2061
2017-09-22 03:34



+1 Hình như cái này nhanh hơn 35% so với phương thức double convert () thường được sử dụng (mà tôi cũng đã sử dụng trong nhiều năm). Đẹp nhất. - Dane
Nhược điểm duy nhất tôi có thể thấy để giải pháp của bạn là trừ khi bạn biết những gì nó đang làm nó là một chút ngớ ngẩn. Sử dụng phương pháp chuyển đổi kép làm cho ý định của bạn rõ ràng hơn đối với các nhà bảo trì mã không dây. BTW Tôi đã không downvoted bạn. Tôi nghĩ tôi cũng sẽ bắt đầu sử dụng phương pháp của bạn. Thankyou @aku - Jim Birchall
@pilavdzice Đặt ngày giờ đến nửa đêm của ngày đó làm Rời khỏi thời gian. Bạn mong đợi kết quả gì? Các datetime loại dữ liệu không thể có không có thời gian chút nào. Tôi nghĩ rằng bạn đang bối rối lưu trữ dữ liệu với bản trình bày của người dùng. Nếu tất cả những gì bạn muốn là một cách để hiển thị cho người dùng một chuỗi không có phần thời gian (không phải là số không, chỉ khoảng trống) thì bạn chỉ muốn Convert(varchar(30), @Date, 101) hoặc một cái gì đó tương tự. Xem Sách SQL Server trực tuyến • Truyền và chuyển đổi để biết thêm thông tin. - ErikE
@ user1671639 kiểu dữ liệu datetime luôn chứa cả ngày tháng và thời gian, bạn không thể lưu trữ một cách hợp lý mà không có cái khác - trừ khi bạn đang sử dụng SQL Server 2008, trong trường hợp đó cũng có dữ liệu 'ngày' và 'thời gian' riêng biệt loại. Nếu bạn sử dụng CONVERT () như thế, bạn thực sự muốn một chuỗi để sử dụng sau này, vì vậy bạn sẽ bị mắc kẹt khi làm như vậy - mặc dù sẽ tốt hơn nếu bạn đã sử dụng chức năng định dạng ngày thay vì cắt ngày - hoặc qua CAST(... AS DATE) hoặc là CONVERT(DATE, ...), đã được đề cập khá thường xuyên trên trang này. - Magnus
Tôi khuyên bạn nên thay đổi câu trả lời thành SELECT DATEADD(dd, DATEDIFF(dd, 0, @your_date), 0) bởi vì lúc đó dd có thể được hoán đổi cho bất kỳ datepart từ khóa để cắt ngắn datetime ở cấp độ tùy ý. - Michael


SQLServer 2008 hiện có kiểu dữ liệu 'ngày' chỉ chứa ngày không có thành phần thời gian. Bất cứ ai sử dụng SQLServer 2008 và hơn thế nữa đều có thể làm như sau:

SELECT CONVERT(date, GETDATE())

657
2017-09-24 13:02



Ngoài ra còn có kiểu dữ liệu 'thời gian' trong SQL2008, câu trả lời cho nửa còn lại của câu hỏi về ngày và giờ tách biệt. - misteraidan
FYI, tôi đã đánh giá các phương pháp khác nhau để cắt giảm thời gian từ ngày và đây là phương pháp nhanh nhất. Cấp sự khác biệt là nhỏ, nhưng rõ ràng là nhanh hơn một số lần thực thi lớn. - UnhandledExcepSean
wt về sqlserver 2005 ?? - Dr. MAF
@ Dr.MAF Hoàn thành vòng tròn, câu trả lời trước năm 2008 là ở đây: stackoverflow.com/questions/113045/… - Frosty840


Nếu sử dụng SQL 2008 trở lên:

select cast(getdate() as date)

141
2018-01-31 09:44



@ FredrickGauss: Loại nào, Ngày? Bạn sử dụng phiên bản SQL Server nào? - abatishchev
Cẩn thận! khai báo @ date1 datetime = '2015-09-30 20: 59: 59.999'; chọn cast (@ date1 as date) trả về '2015-10-01' - Nick
@ Nick: đây là vấn đề với DateTime. sử dụng DateTime2 thay vào đó và nó hoạt động tốt. sqlfiddle.com/#!6/9eecb7/2833 - abatishchev
@Nick, để bổ sung cho phản hồi abatishchev, ngày @ date1 của bạn thực sự 2015-10-01, do DateTime hạn chế. Hãy thử mà không có bất kỳ diễn viên nào Date, nó mang lại 2015-10-01quá! declare @date1 datetime = '2015-09-30 23:59:59.999';select @date1 => 2015-10-01 - Frédéric
Một trong những cách dễ nhớ các thủ thuật SQL. Như Mike nói, chỉ năm 2008 trở đi nhưng, nếu bạn tìm thấy một năm 2005 và trước đó DB một nơi nào đó, bạn có thể có rất nhiều vấn đề :) - NicVerAZ


DATEADD và DATEDIFF tốt hơn CONVERTing thành varchar. Cả hai truy vấn đều có cùng một kế hoạch thực hiện, nhưng các kế hoạch thực hiện chủ yếu là về dữ liệu truy cập chiến lược và không luôn luôn tiết lộ chi phí tiềm ẩn liên quan đến thời gian CPU được thực hiện để thực hiện tất cả các phần. Nếu cả hai truy vấn được chạy với một bảng có hàng triệu hàng, thời gian CPU sử dụng DateDiff có thể gần bằng 1/3 thời gian chuyển đổi CPU!

Để xem các kế hoạch thực hiện cho các truy vấn:

set showplan_text on
GO 

Cả DATEADD và DATEDIFF sẽ thực thi CONVERT_IMPLICIT.

Mặc dù giải pháp CONVERT đơn giản và dễ đọc hơn,  chậm hơn. Không cần phải quay trở lại datetime (điều này hoàn toàn được thực hiện bởi máy chủ). Cũng không có nhu cầu thực sự nào trong phương thức DateDiff cho DateAdd sau đó vì kết quả số nguyên cũng sẽ được chuyển đổi hoàn toàn về datetime.


SELECT CONVERT (varchar, MyDate, 101) TỪ DatesTable

  |--Compute Scalar(DEFINE:([Expr1004]=CONVERT(varchar(30),[TEST].[dbo].[DatesTable].[MyDate],101)))
       |--Table Scan(OBJECT:([TEST].[dbo].[DatesTable]))

CHỌN DATEADD (đ, 0, DATEDIFF (đ, 0, MyDate)) TỪ DatesTable

  |--Compute Scalar(DEFINE:([Expr1004]=dateadd(day,(0),CONVERT_IMPLICIT(datetime,datediff(day,'1900-01-01 00:00:00.000',CONVERT_IMPLICIT(datetime,[TEST].[dbo].[DatesTable].[MyDate],0)),0))))
       |--Table Scan(OBJECT:([TEST].[dbo].[DatesTable]))

Sử dụng FLOOR () như @digi được đề xuất có hiệu suất gần hơn với DateDiff, nhưng không được khuyến nghị khi truyền kiểu dữ liệu datetime để float và back không luôn mang lại giá trị ban đầu.

Nhớ các bạn: Đừng tin ai cả. Nhìn vào số liệu thống kê hiệu suất và tự mình kiểm tra!

Hãy cẩn thận khi bạn kiểm tra kết quả của mình. Việc chọn nhiều hàng cho máy khách sẽ ẩn sự khác biệt hiệu suất vì phải mất nhiều thời gian hơn để gửi các hàng qua mạng hơn là thực hiện các phép tính. Vì vậy, hãy chắc chắn rằng công việc cho tất cả các hàng được thực hiện bởi máy chủ nhưng không có rowset được gửi đến máy khách.

Dường như có sự nhầm lẫn đối với một số người về thời điểm tối ưu hóa bộ nhớ cache ảnh hưởng đến truy vấn. Chạy hai truy vấn trong cùng một lô hoặc trong các lô riêng biệt không ảnh hưởng đến bộ nhớ đệm. Vì vậy, bạn có thể hết hạn bộ nhớ cache theo cách thủ công hoặc chỉ cần chạy truy vấn qua lại nhiều lần. Bất kỳ tối ưu hóa cho truy vấn # 2 cũng sẽ ảnh hưởng đến bất kỳ truy vấn tiếp theo nào, vì vậy hãy thực hiện # 1 nếu bạn muốn.

Đây là tập lệnh thử nghiệm đầy đủ và kết quả hiệu suất chứng minh DateDiff nhanh hơn đáng kể so với chuyển đổi thành varchar.


67
2017-09-22 03:33



Ricardo C, điều tra tốt đẹp! Bạn sử dụng phiên bản máy chủ SQL nào? Về phương pháp MSSQL2000 với dateiff thực hiện hơi nhanh hơn cho tôi. - aku
Chỉ cần lưu ý, tôi đã thực hiện bài kiểm tra 1000.000 lần. Đối với các kịch bản thực tế, sự khác biệt về hiệu suất sẽ không đáng chú ý, tôi đoán - aku
Aku, tôi đã sử dụng SQL Server 2005 Express cho thử nghiệm này. Tôi làm việc vào năm 2000 tại nơi làm việc, và tôi sẽ thử nghiệm nó với một bảng với hơn 24 triệu hàng và xem những gì xuất phát từ nó. - Ricardo C
Aku, cùng một kết quả. Không có sự khác biệt về hiệu suất trên mười triệu hàng. - Ricardo C
Các tuyên bố về hiệu suất bằng nhau là không đúng sự thật. Tất nhiên kế hoạch thực hiện sẽ giống nhau !!! Đo hiệu suất trên những PHẢI được thực hiện bằng cách so sánh việc sử dụng CPU, không kiểm tra kế hoạch thực hiện. - ErikE


SELECT CONVERT(VARCHAR(10),GETDATE(),111)

41
2017-09-22 03:33



Điều này trả về '2008/09/22' cho tôi - eddiegroves
111 là định dạng tiếng Nhật. yyy / mm / dd - Ricardo C
SELECT CONVERT (VARCHAR (10), GETDATE (), 101) là mm/dd/yyyy định dạng. - Flea
nếu bạn sắp xếp dựa trên giá trị văn bản thô (bên ngoài DB) thì định dạng 'tiếng Nhật' tốt hơn - Simon_Weaver
Nó hoạt động trên SQL Server 2005. - Raphael Amoedo


SELECT CONVERT(datetime, CONVERT(varchar, GETDATE(), 101))

35
2017-09-22 03:34





Bạn có thể dùng CONVERT chỉ trả về ngày tháng. Xem (các) liên kết dưới đây:

Ngày và thời gian thao tác trong SQL Server 2000

CAST và CONVERT

Cú pháp để sử dụng hàm chuyển đổi là:

CONVERT ( data_type [ ( length ) ] , expression [ , style ] ) 

18
2017-12-19 06:48





Để trả về định dạng ngày 

CAST (Ngày đặt hàng AS)

Đoạn mã trên sẽ hoạt động trong máy chủ sql 2010

Nó sẽ trở lại như 12/12/2013

Đối với SQL Server 2012, sử dụng mã bên dưới

CONVERT(VARCHAR(10), OrderDate , 111)

17
2017-09-22 07:38



Điều này trả về cho tôi ngày không có thời gian, không chỉ ngày tháng - Bohemian♦
tôi có thể biết phiên bản nào nếu máy chủ sql bạn đang sử dụng? - Mahesh ML
@MaheshML nó trả về cả ngày và giờ trong MS SQL 2012. - Marek
@ Marek Nó hoạt động tốt với MS SQL 2008 - Mahesh ML
@MaheshML Không có những thứ như SQL Server 2010. - SvenAelterman


Sử dụng FLOOR () - chỉ cần cắt một phần thời gian.

SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)

12
2017-09-22 12:21



Phương pháp này không phải là nhanh nhất, và cũng ngầm dạy cho mọi người rằng các ngày đúc để nổi là chính xác, mà nó không phải là. Xin vui lòng xem bài này để biết thêm chi tiết. - ErikE
Lỗi định lượng nổi là đáng sợ - messenger


SELECT CONVERT(VARCHAR,DATEADD(DAY,-1,GETDATE()),103) --21/09/2011

SELECT CONVERT(VARCHAR,DATEADD(DAY,-1,GETDATE()),101) --09/21/2011

SELECT CONVERT(VARCHAR,DATEADD(DAY,-1,GETDATE()),111) --2011/09/21

SELECT CONVERT(VARCHAR,DATEADD(DAY,-1,GETDATE()),107) --Sep 21, 2011

12
2017-07-26 20:00