Làm tròn SQL DateTime thành nửa đêm


81

Tôi đang gặp sự cố nhỏ với truy vấn SQL của mình. Tôi đang sử dụng hàm GETDATE, tuy nhiên, giả sử tôi thực thi tập lệnh lúc 5 giờ chiều, nó sẽ kéo lên các bản ghi từ 5 giờ chiều ngày 12/12/2011 đến 18 giờ chiều ngày 18/12/2011. Làm thế nào tôi có thể làm cho nó kéo hồ sơ cho toàn bộ 12/12/2011 - 18/12/2011 về cơ bản bỏ qua thời gian.

Kịch bản của tôi:

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate > (GETDATE()-6)  

Câu trả lời:


114

Trong SQL Server 2008 và mới hơn, bạn có thể truyền DateTimetới a Date, điều này sẽ loại bỏ phần tử thời gian.

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate >= (cast(GETDATE()-6 as date))  

Trong SQL Server 2005 trở xuống, bạn có thể sử dụng:

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate >= DateAdd(Day, Datediff(Day,0, GetDate() -6), 0)

1
Tôi đã nhận Loại ngày này không phải là một loại hệ thống xác định.
henryaaron

2
Tôi đoán bạn không sử dụng SQL 2008 rồi :)
DaveShaw

@ user1090389 rằng lý do tại sao tôi đặt tùy chọn chuỗi chuyển đổi; D
Bassam Mehanni

@DaveShaw - Bỏ lỡ một DATEADD trong đó
MatBailie

Vẻ xin lỗi @Dems Dave ít phức tạp
henryaaron

54

Đây là điều đơn giản nhất tôi đã tìm thấy

-- Midnight floor of current date

SELECT Convert(DateTime, DATEDIFF(DAY, 0, GETDATE()))

DATEDIFF trả về số nguyên của ngày trước hoặc kể từ năm 1900-1-1 và Ngày giờ chuyển đổi bắt buộc đưa nó trở lại ngày đó lúc nửa đêm.

Vì DateDiff trả về một số nguyên nên bạn có thể sử dụng phép cộng hoặc trừ ngày để có được phần bù phù hợp.

SELECT Convert(DateTime, DATEDIFF(DAY, 0, GETDATE()) + @dayOffset)

Đây không phải là làm tròn mà là cắt ngắn ... Nhưng tôi nghĩ đó là những gì đang được hỏi. (Để làm tròn, hãy thêm một và cắt ngắn ... và điều đó cũng không làm tròn, đó là trần, nhưng rất có thể là những gì bạn muốn. Để thực sự làm tròn, hãy thêm .5 (điều đó có hoạt động không?) Và cắt ngắn.

Hóa ra bạn có thể thêm .5 vào GetDate () và nó hoạt động như mong đợi.

-- Round Current time to midnight today or midnight tomorrow

SELECT Convert(DateTime, DATEDIFF(DAY, 0, GETDATE() + .5))

Tôi đã thực hiện tất cả các thử nghiệm của mình trên SQL Server 2008, nhưng tôi nghĩ rằng các chức năng này cũng áp dụng cho năm 2005.


Điều này hoạt động trong 2k5 vừa thử nghiệm nó. where [ScanDate] >= convert(datetime, datediff(day, 0, getdate())) and [ScanDate] < convert(datetime, datediff(day, -1, getdate()))
nulltron

9
--
-- SQL DATEDIFF getting midnight time parts 
--
SELECT GETDATE() AS Now, 
   Convert(DateTime, DATEDIFF(DAY, 0, GETDATE())) AS MidnightToday,
   Convert(DateTime, DATEDIFF(DAY, -1, GETDATE())) AS MidnightNextDay,
   Convert(DateTime, DATEDIFF(DAY, 1, GETDATE())) AS MidnightYesterDay
go
Now                   MidnightToday          MidnightNextDay        MidnightYesterDay     
 --------------------  ---------------------  ---------------------  --------------------- 
 8/27/2014 4:30:22 PM  8/27/2014 12:00:00 AM  8/28/2014 12:00:00 AM  8/26/2014 12:00:00 AM 

5
SELECT getdate()

Kết quả: 2012-12-14 16: 03: 33.360

SELECT convert(datetime,convert(bigint, getdate()))

Kết quả 2012-12-15 00: 00: 00.000


1
Cảm ơn vì bạn đã phản hồi. Những gì tôi đang cố gắng làm nổi bật rằng chuyển đổi thành bigint và quay lại thực hiện việc làm tròn cho bạn.
Jeremy Atkinson

1
Mã này làm tròn nó đến nửa đêm vào cuối ngày nếu thời gian sau giữa trưa khiến mã này bị sai trong nửa ngày.
ChrisM

Sử dụng phương pháp này có thể gây ra các tác động về hiệu suất sau này với các bộ dữ liệu lớn hơn.
Taco タ コ ス

3

Như @BassamMehanni đã đề cập, bạn có thể truyền dưới dạng DATE trong SQL Server 2008 trở đi ...

SELECT
  *
FROM
  yourTable
WHERE
      dateField >= CAST(GetDate() - 6 AS DATE)
  AND dateField <  CAST(GetDate() + 1 AS DATE)

Điều kiện thứ hai thực tế có thể chỉ là GetDate(), nhưng tôi đang hiển thị định dạng này như một ví dụ Less Than DateXđể tránh phải truyền dateField thành DATE, do đó cải thiện hàng loạt hiệu suất.


Nếu bạn từ 2005 trở xuống, bạn có thể sử dụng ...

SELECT
  *
FROM
  yourTable
WHERE
      dateField >= DATEADD(DAY, DATEDIFF(DAY, 0, GetDate()) - 6, 0)
  AND dateField <  DATEADD(DAY, DATEDIFF(DAY, 0, GetDate()) + 1, 0)

3

Hãy thử sử dụng cái này.

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate >= CONVERT(DATE, GETDATE())

1

Cái này có vẻ rẻ nhưng nó hiệu quả với tôi

CHỌN CHUYỂN ĐỔI (DATETIME, LEFT (CHUYỂN ĐỔI (VARCHAR, @ dateFieldOrVariable, 101), 10) + '00: 00: 00.000')


1

Bạn có thể chuyển đổi datetime thành một ngày rồi quay lại datetime. Điều này sẽ đặt lại dấu thời gian.

chọn getdate () --2020-05-05 13: 53: 35.863

chọn truyền (cast (GETDATE () as date) as datetime) --2020-05-05 00: 00: 00.000

0

tôi thường làm

SELECT *
FROM MyTable
WHERE CONVERT(VARCHAR, MyTable.dateField, 101) = CONVERT(VARCHAR, GETDATE(), 101)

nếu bạn đang sử dụng SQL SERVER 2008, bạn có thể làm

SELECT *
FROM MyTable
WHERE CAST(MyTable.dateField AS DATE) = CAST(GETDATE() AS DATE)

Hi vọng điêu nay co ich


3
Nếu bạn sử dụng ví dụ đầu tiên, bạn sẽ hủy khả năng sử dụng chỉ mục của người tối ưu, v.v. Sử dụng các hàm Chuỗi để thực hiện số học và so sánh ngày là một ý tưởng rất tồi. Nó thậm chí không nên được đề cập đến (imo), đó là một lựa chọn kém.
MatBailie

Bạn không cần phải làm như vậy nếu bạn đang sử dụng SQL Server 2008, nếu không, tôi không chắc bạn có thể làm điều đó bằng cách nào khác trong SQL Server 2000/2005, một ví dụ sẽ được đánh giá cao, cảm ơn.
Bassam Mehanni

Để có sự công bằng. Cả hai tùy chọn đều phá hủy khả năng sử dụng chỉ mục của optmizer. Bạn nên thực hiện và chức năng trên cột vị ngữ bộ lọc. Điều này bao gồm phôi.
pim

0

Bạn có thể làm tròn thời gian.

Sử dụng ROUNDbên dưới sẽ làm tròn nó xuống nửa đêm.

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate >  CONVERT(datetime, (ROUND(convert(float, getdate()-6.5),0)))
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.