2011-08-22 42 views
13

Tôi đang cố gắng tạo một bảng với một chuỗi các ngày tháng trong đó.SQL Server 2008 Tạo một chuỗi ngày giờ

Tôi có thời gian ngày bắt đầu và ngày kết thúc được chỉ định (thời gian ngày kết thúc là kết thúc chuỗi), tôi thêm khoảng thời gian ~ (điều này có thể thay đổi) vào thời gian ngày bắt đầu tính bằng giây và điều này cho tôi ngày kết thúc thời gian.

Chuỗi tiếp theo sử dụng thời gian ngày kết thúc làm giá trị bắt đầu và thêm khoảng thời gian tính bằng giây vào nó. Để chứng minh đầu ra tôi cần. Có một cách nhanh chóng để tạo ra một bảng như vậy, ngoại trừ sử dụng rất nhiều chèn vào lệnh ?, Tôi thực sự bối rối

StartTime    Endtime     Duration 
2011-07-20 11:00:33  2011-07-20 11:09:47  554 
2011-07-20 11:09:47  2011-07-20 11:19:01  554 

    declare @StartTime datetime = '2011-07-20 11:00:33', 
    @EndTime datetime = '2011-07-20 15:37:34' 
    @Interval int = 554 -- this can be changed. 

    insert into tmp_IRange 
    values('2011-07-20 11:00:33', DATEADD(SECONDS, @Duration, 2011-07-20 11:00:33)) 

này trở nên rất tẻ nhạt .. đặc biệt là khi thời gian ngày kết thúc là 2011-07-20 15:37:34 có rất nhiều báo cáo chèn để làm :(

+2

Bạn không thực sự chứng minh đầu ra của mình. Bạn có thể hiển thị ba dòng đầu tiên và cuối cùng mà bạn thực sự muốn không? –

+1

Lưu ý rằng các câu trả lời dựa trên CTE đệ quy có giới hạn 32767 mức đệ quy. (Xem tài liệu MAXRECURSION.) – HABO

+2

@ user92546 - Đó không phải là trường hợp. 'MAXRECURSION 0' không giới hạn. –

Trả lời

4

Điều này sẽ giúp bạn bắt đầu. bạn có thể thích ứng với nhu cầu cụ thể của bạn. Theo văn bản nó sẽ tạo ra một hàng cho mỗi increment phút bắt đầu với ngày hiện tại & thời gian.

DECLARE @BaseDate DateTime = GETDATE(); 

WITH DateTable (DateValue) AS (
    SELECT @BaseDate DateValue 
    UNION ALL 
    SELECT DATEADD(Minute, 1, DateValue) DateValue 
    FROM DateTable 
) 
SELECT * 
FROM DateTable 
WHERE DateValue < DATEADD(Day, 1, GETDATE()) 
OPTION (MAXRECURSION 0); 
+0

Nó tăng 1 giây, phải không? – JNK

+0

@JNK: Có, chỉnh sửa mô tả và gia số. Vì nó đã được, truy vấn sẽ chạy trong một thời gian! – Yuck

+0

Vâng, bạn chỉ có một biến datetime duy nhất trong khi OP có hai biến datetime và một khoảng thời gian.Tại sao không có gì trong giải pháp của bạn về khoảng thời gian (554 giây) và ngày kết thúc (bạn cho rằng đó là khoảng thời gian 1 phút trong một ngày)? –

16

Sử dụng một CTE đệ quy

declare @StartTime datetime = '2011-07-20 11:00:33', 
    @EndTime datetime = '2011-07-20 15:37:34', 
    @Interval int = 554 -- this can be changed. 

;WITH cSequence AS 
(
    SELECT 
     @StartTime AS StartRange, 
     DATEADD(SECOND, @Interval, @StartTime) AS EndRange 
    UNION ALL 
    SELECT 
     EndRange, 
     DATEADD(SECOND, @Interval, EndRange) 
    FROM cSequence 
    WHERE DATEADD(SECOND, @Interval, EndRange) < @EndTime 
) 
/* insert into tmp_IRange */ 
SELECT * FROM cSequence OPTION (MAXRECURSION 0); 
+0

Là Khoảng thời gian được sử dụng trong truy vấn này, dường như có biến Thời lượng không khai báo trong truy vấn này. – jrara

+0

@jrara: cảm ơn, đã sửa – gbn

+0

Làm việc nhờ điều trị – mouse

5

Cái này sẽ cung cấp cho các dãy cá nhân nhưng sẽ bỏ qua thời gian cuối thực tế của bạn (vì nó là < @interval sau khi phạm vi hợp lệ cuối cùng):

;WITH x AS 
(
    SELECT TOP (DATEDIFF(SECOND, @StartTime, @EndTime)/@Interval) 
     rn = ROW_NUMBER() OVER (ORDER BY [object_id]) 
    FROM sys.objects 
) 
-- INSERT INTO dbo.tmp_IRange 
SELECT DATEADD(SECOND, @Interval * (rn-1), @StartTime), 
    DATEADD(SECOND, @Interval * rn, @StartTime) 
FROM x; 
+0

* 'Chuỗi tiếp theo sử dụng thời gian Ngày kết thúc làm giá trị bắt đầu' *, có nghĩa là thời gian bắt đầu không phải là giá trị cố định. –

+0

Cảm ơn @Andriy, đã bỏ lỡ điều đó; đã xóa câu trả lời đầu tiên. –

0

Hy vọng điều này giúp ...

declare @StartTime datetime = '2011-07-20 11:00:33', 
@EndTime datetime = '2011-07-20 11:00:33', 
@Interval int = 554, 

@LimitTime datetime = '2011-07-20 15:37:34' 

WHILE @EndTime < @LimitTime 
BEGIN 
SELECT @EndTime = DATEADD(S, @Interval, @StartTime) 

SELECT @StartTime, @EndTime 
--INSERT INTO tmp_IRange VALUES(@StartTime, @EndTime) 

SELECT @StartTime = @EndTime 

END 
0

hãy thử mã này:

create table #T (date_begin datetime, date_end datetime)  

declare @StartTime datetime = '2011-07-20 11:00:33', 
    @EndTime datetime = '2011-07-20 15:37:34', 
    @Interval int = 554 -- this can be changed. 

while DATEADD(ss,@Interval,@StartTime)<[email protected] 
begin 
    insert #T 
    select @StartTime, DATEADD(ss,@Interval,@StartTime) 

    set @StartTime = DATEADD(ss,@Interval,@StartTime) 
end 


select * from #T 
3

Đây là một giải pháp thiết lập dựa trên không đệ quy, trong đó sử dụng một bảng hệ thống gọi là master..spt_values:

DECLARE 
    @StartTime datetime = '2011-07-20 11:00:33', 
    @EndTime datetime = '2011-07-20 15:37:34', 
    @Interval int = 554; 
SELECT 
    StartTime = DATEADD(SECOND, (number - 1) * @Interval, @StartTime), 
    EndTime = DATEADD(SECOND, (number - 0) * @Interval, @StartTime), 
    Duration = @Interval 
FROM master..spt_values 
WHERE type = 'P' 
    AND number BETWEEN 1 AND DATEDIFF(SECOND, @StartTime, @Endtime)/@Interval 

UNION ALL 

SELECT 
    DATEADD(SECOND, -Duration, EndTime), 
    EndTime, 
    Duration 
FROM (
    SELECT 
    EndTime = @EndTime, 
    Duration = DATEDIFF(SECOND, @StartTime, @Endtime) % @Interval 
) s 
WHERE Duration > 0 

SELECT đầu tiên tạo ra một tập hợp hàng bao gồm khoảng thời gian ngắn có độ dài xác định rằng nằm trong phạm vi chỉ định. Nếu cần thiết, lệnh SELECT thứ hai thêm một khoảng thời gian giữa thời gian kết thúc của khoảng thời gian cuối cùng của SELECT và thời gian kết thúc được chỉ định.

Tập hợp con master..spt_values được sử dụng đặc biệt ở đây (và có thể được sử dụng trong nhiều trường hợp tương tự) cung cấp danh sách các số từ 0 đến 2047. Điều này có nghĩa là bạn sẽ không thể sử dụng giải pháp này với bảng đó nếu khoảng thời gian ban đầu sẽ được chia thành nhiều khoảng thời gian 2047 ngắn hơn (er). Sau đó bạn nên nghĩ về một cái gì đó như của riêng bạn number table.

+0

+1 nhưng hãy gọi nó là bảng số hoặc số, không phải bảng kiểm đếm. Nó là một bảng số, không phải là một bảng tổng hợp. :-) –

+0

Không sao cả! Tôi nghĩ rằng hai thuật ngữ hoàn toàn có thể hoán đổi cho nhau. Mặc dù tôi thừa nhận, tôi không thể hiểu đầy đủ tất cả sự tinh tế về ý nghĩa của từ * kiểm đếm * (và sau đó tôi nên thận trọng hơn trong tập quán trước đây của tôi về thuật ngữ * bảng kiểm đếm *). Cảm ơn bạn rất nhiều vì đã thông báo! –

+1

Jeff Moden đang cố gắng "tái tạo lại" ý tưởng bảng số (mà không có nguồn gốc từ anh ta) bằng cách đổi tên nó. Vì vậy, các cuộc thảo luận phát triển nơi hai người đang sử dụng các thuật ngữ khác nhau và có thể gây nhầm lẫn. Bảng số * có thể * được sử dụng để kiểm đếm, nhưng đó chỉ là một trường hợp sử dụng rất cụ thể, ngay cả khi nó là một trong những số phổ biến hơn. Dù sao, đây chỉ là ý kiến ​​của tôi, hoàn toàn chủ quan, nhưng tôi cố gắng để bắn hạ sự gia tăng của thuật ngữ "bảng kiểm đếm" khi tôi nghĩ mọi người có thể nghe. :-) –

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