2010-07-20 53 views
5

Tôi có bảng có dấu thời gian và tôi muốn phân đoạn bảng này thành các khoảng thời gian một giờ, bắt đầu từ bây giờ và ngược lại một vài giờ. Tôi không thể nhận được kết quả tôi cần với chức năng T-SQL DATEDIFF, vì nó đếm số lần kim phút trôi qua 12 giữa hai ngày - tôi muốn số lần chúng di chuyển qua phút khi nó ở ngay bây giờ giữa dấu thời gian và bây giờ.T-SQL DateDiff - phân vùng theo "toàn bộ giờ trước", thay vì "số phút đã chuyển 00 kể từ"

Có cách nào đơn giản để thực hiện việc này trong T-SQL không?

Cập nhật: Để trả lời nhận xét, đây là một số dữ liệu mẫu, truy vấn tôi hiện đang sử dụng và kết quả tôi nhận được, cũng như kết quả tôi muốn.

dữ liệu mẫu:

TimeStamp 
********* 
2010-07-20 11:00:00.000 
2010-07-20 10:44:00.000 
2010-07-20 10:14:00.000 
2010-07-20 11:00:00.000 
2010-07-20 11:40:00.000 
2010-07-20 10:16:00.000 
2010-07-20 13:00:00.000 
2010-07-20 12:58:00.000 

truy vấn hiện tại:

SELECT TimeStamp, DATEDIFF(HOUR, TimeStamp, CURRENT_TIMESTAMP) AS Diff FROM ... 

Kết quả:

 TimeStamp     Diff 
    *********     **** 
    2010-07-20 11:00:00.000  2 
    2010-07-20 10:44:00.000  3 
    2010-07-20 10:14:00.000  3 
    2010-07-20 11:00:00.000  2 
    2010-07-20 11:40:00.000  2 
    2010-07-20 10:16:00.000  3 
    2010-07-20 13:00:00.000  0 
    2010-07-20 12:58:00.000  1

Những gì tôi thà có:

 -- The time is now, for the sake of the example, 13:40 

    TimeStamp     Diff 
    *********     **** 
    2010-07-20 11:00:00.000  3 -- +1 
    2010-07-20 10:44:00.000  3 
    2010-07-20 10:14:00.000  4 -- +1 
    2010-07-20 11:00:00.000  3 -- +1 
    2010-07-20 11:40:00.000  2 or 3 -- edge case, I don't really care which 
    2010-07-20 10:16:00.000  4 -- +1 
    2010-07-20 13:00:00.000  1 -- +1 
    2010-07-20 12:58:00.000  1

Tôi đã đánh dấu kết quả đã thay đổi bằng một số +1. Ngoài ra, tôi không thực sự quan tâm nếu điều này là 0-lập chỉ mục hoặc 1-lập chỉ mục, nhưng về cơ bản, nếu nó bây giờ 13:40 Tôi muốn các nhịp thời gian đó có được giá trị như nhau để được

 12:40-13:40 1 (or 0) 
    11:40-12:40 2 (or 1) 
    10:40-11:40 3 (or 2) 
    09:40-10:40 4 (or 3)
+0

bạn có thể giải thích điều đó với dữ liệu đầu vào và đầu ra mong đợi với các truy vấn, bạn đã viết? – shahkalpesh

+0

DATEDIFF trong vài phút sau đó chia số nguyên cho 60? –

Trả lời

7

Can bạn không chỉ cần sử dụng DATEDIFF(minute,.. và sau đó chia kết quả cho 60 và lấy giá trị số nguyên. ví dụ.

SELECT DATEDIFF(minute, '2010-07-20 06:00', GETDATE())/60 

Tôi tin rằng điều này sẽ được ngầm sử dụng như một int khi dateiff trả về một int, nó cho toàn bộ giờ không làm tròn.

Để sử dụng truy vấn chính xác của bạn từ bài cập nhật của bạn:

SELECT TimeStamp, (DATEDIFF(minute, TimeStamp, CURRENT_TIMESTAMP) /60) AS Diff FROM ... 
+0

Điều này vẫn không chính xác. Bạn vừa thay đổi lỗi từ 59 phút đến 59 giây ... – ErikE

+0

@Emtucifor: Lỗi 59 giây vẫn tốt hơn nhiều - tôi sẽ sử dụng điều này để quyết định liệu người dùng có nhận được thông báo hay không và họ chỉ nên nhận được nhiều nhất một giờ. Một lỗi của 59 phút trong trường hợp đó là thảm khốc - một lỗi 59 giây là khá tốt. Và tôi thậm chí có thể nhận được lỗi thậm chí còn nhỏ hơn (<1 giây) bằng cách làm điều tương tự với giây như Ben làm với phút. –

+0

Ok, không sao cả. Tuy nhiên, tôi thích phiên bản trừ ngày của tôi tốt hơn, bởi vì nó thậm chí còn đơn giản hơn và nó chính xác như kiểu dữ liệu cho phép. :) – ErikE

0

Bạn có thể nhóm về vấn đề này:

SELECT DateDiff(Hour, 0, GetDate() - TimeStamp) 

Nếu bạn muốn biết thời gian này đại diện, calc nó trở lại:

DateAdd(Hour, -DateDiff(Hour, 0, GetDate() - TimeStamp), GetDate()) 

Nếu bạn không thích trừ ngày, sau đó nó vẫn có thể được thực hiện nhưng trở nên khó hơn một chút. Thay vì chỉ chụp trong bóng tối, tôi đã thực hiện một truy vấn để chứng minh điều này là chính xác.

SELECT 
    TimeStamp, 
    Now = GetDate(), 
    HourDiff = DateDiff(Hour, 0, GetDate() - TimeStamp), 
    HourCalc = DateAdd(Hour, -DateDiff(Hour, 0, GetDate() - TimeStamp), GetDate()), 
    HourDiff2 = DateDiff(Hour, DateAdd(Millisecond, AdjustMs, TimeStamp), DateAdd(Millisecond, AdjustMs, GetDate())), 
    HourCalc2 = DateAdd(Hour, -DateDiff(Hour, DateAdd(Millisecond, AdjustMs, TimeStamp), DateAdd(Millisecond, AdjustMs, GetDate())), GetDate()) 
FROM 
    (
     SELECT DateAdd(Second, -3559, GetDate()) 
     UNION ALL SELECT DateAdd(Second, -3600, GetDate()) 
     UNION ALL SELECT DateAdd(Second, -3601, GetDate()) 
    ) x (TimeStamp) 
    CROSS JOIN (
     SELECT 3599997 - DateDiff(Millisecond, 0, DateAdd(Hour, -DateDiff(Hour, 0, GetDate()), GetDate())) 
    ) D (AdjustMs) 

Thật không may, tôi đã có để khai thác kiến ​​thức của tôi về nghị quyết datetime datatype của (1/300 của một giây), do đó 3.600.000-3 = 3599997. Nếu việc điều chỉnh một phần nghìn giây đã được tính toán dựa trên các dấu thời gian thay vì getdate () thì điều này sẽ không cần thiết, nhưng sẽ rất lộn xộn hơn vì biểu thức lớn bên trong bảng D có nguồn gốc sẽ phải được sử dụng hai lần trong truy vấn chính, thay thế AdjustMs.

Tính toán phức tạp hơn có vẻ cần thiết vì bạn không thể tính toán sai số mili giây giữa các ngày ngẫu nhiên hoặc bạn sẽ gặp phải lỗi tràn. Nếu bạn biết phạm vi ngày có thể, bạn có thể thoát khỏi việc thực hiện các phép tính milli giây trực tiếp bằng cách sử dụng ngày neo khác với '19000101 00: 00: 00.000' (số 0 trong các biểu thức trên).

Ngày nghĩ thứ hai, bạn chỉ nhận được 24+ ngày mili giây vào một ký dài:

SELECT DateAdd(Millisecond, 2147483647, 0) = '1900-01-25 20:31:23.647' 
+0

Điều đó có vẻ giống như đi một chặng đường dài để tránh trừ ngày - nhưng từ bài đăng của bạn, tôi lấy nó có thể có lý do chính đáng để không muốn làm điều đó. Tại sao tôi không muốn trừ ngày? –

+0

Vâng, nó không phải là một yêu cầu trong trường hợp này với ** datetime **, nhưng trong SQL Server 2008 bạn không thể cộng hoặc trừ các giá trị của kiểu dữ liệu ** date **. Mặc dù làm như vậy với ** datetime ** hoạt động ngay bây giờ, nó có thể không mãi mãi. C#. Net cũng cấm điều này (bạn chỉ có thể cộng và trừ các khoảng thời gian từ ngày tháng hoặc các khoảng thời gian khác) vì vậy tất cả chúng ta nên suy nghĩ về các cách để tránh nó nếu chúng ta sẽ ở trên đầu trang của công cụ này trong thời gian dài. Một số ngày trừ đi thời gian biểu có thể không được chấp nhận và sau đó bị loại bỏ như một tính năng! – ErikE

0

Tôi muốn sử dụng

FLOOR(24 * CAST(CURRENT_TIMESTAMP-[TimeStamp] as float)) 

Test Case

DECLARE @GetDate datetime 
set @GetDate = '2010-07-20 13:40:00.000'; 

WITH TestData As 
(
select CAST('2010-07-20 11:00:00.000' AS DATETIME) AS [TimeStamp] UNION ALL 
select '2010-07-20 10:44:00.000' UNION ALL  
select '2010-07-20 10:14:00.000' UNION ALL 
select '2010-07-20 11:00:00.000' UNION ALL 
select '2010-07-20 11:40:00.000' UNION ALL 
select '2010-07-20 10:16:00.000' UNION ALL 
select '2010-07-20 13:00:00.000' UNION ALL 
select '2010-07-20 12:58:00.000' 
) 

SELECT [TimeStamp], FLOOR(24 * CAST(@GetDate-[TimeStamp] as float)) AS Diff 
FROM TestData 

Kết quả

(Bạn sẽ cần phải thêm 1 để có được kết quả chính xác mà bạn đăng tải nhưng bạn nói rằng bạn đang không làm phiền về 0 hoặc 1 lập chỉ mục)

TimeStamp    Diff 
----------------------- ---------------------- 
2010-07-20 11:00:00.000 2 
2010-07-20 10:44:00.000 2 
2010-07-20 10:14:00.000 3 
2010-07-20 11:00:00.000 2 
2010-07-20 11:40:00.000 2 
2010-07-20 10:16:00.000 3 
2010-07-20 13:00:00.000 0 
2010-07-20 12:58:00.000 0 
+0

Tại sao '24 *'? 'CAST (@ GetDate- [TimeStamp] AS FLOAT)' cung cấp cho tôi những gì? –

+0

@Tomas. 'CAST (@ GetDate- [TimeStamp] AS FLOAT)' là số ngày khác nhau. ví dụ. 1,75 sẽ là 1 ngày và 18 giờ khác biệt. Vì vậy, nhân với 24 cho số giờ khác nhau. Sử dụng 'Floor' sau đó nhóm tất cả mọi thứ trong một giờ với nhau. –

+0

Martin, trong kinh nghiệm của tôi chuyển đổi sang phao là không đáng tin cậy cho datetime. Tôi đã chăm chú nghiên cứu điều này trong quá khứ. Datediff (Giờ, 0, Current_TimeStamp - TimeStamp) thực hiện cùng một thủ thuật. – ErikE

Các vấn đề liên quan