2010-11-17 4 views
5

Hai bảng tạm thời được tạo và sau đó được nạp ... Đây là lược đồ.Kịch bản lệnh T-SQL - các vấn đề logic với dòng thời gian

Create table #SH ([date] datetime, 
     sched_id int, 
     agent_id int) 

Create table #SD (sched_id int, 
     start_minute int, 
     length int, 
     exception_code int) 

(Giản đồ và thiết kế là thứ tôi không thể thay đổi, cả bảng tạm thời đều được tải từ tệp phẳng. Tôi có thể giới thiệu và tải bảng tạm thời mới nếu cần).

Một nền nhỏ - Bảng tiêu đề #SH giữ lịch biểu người là 'Start_minute' và chuyển sang 'schedule_length' trong vài phút. Ví dụ: nếu phút bắt đầu và thời lượng lịch biểu là cả 480, sẽ đọc là 8 giờ sáng (8am = 480 phút) và đến 4 giờ chiều (480 phút sau, 4 giờ chiều = 960 phút)

Bảng #SD chứa ngoại lệ đối với tiêu đề. Trong ví dụ trên, người đó có thể sẽ có ngoại lệ cho bữa trưa sẽ là start_minute = 720 và chiều dài 30 (12:00 - 12:30).

Ngày và agent_id là điều duy nhất tôi quan tâm ra khỏi #SH, các thông tin ngoại lệ trong #sd là những gì tôi đang quan tâm đến việc

truy vấn này:.

Select [date],#sd.start_minute,#sd.length,#sd.start_minute + #sd.length as 'end_minute',agent_id 
from #SH 
inner join #SD on #SD.sched_id = #sh.sched_id 

* end_minute là cuối cùng một giá trị tính toán của mình bắt đầu + chiều dài = cuối

này trả về một cái gì đó như:

Date  Start length end 

1 2010-11-11 600 30 630 

2 2010-11-11 630 40 670 

3 2010-11-11 750 15 765 

4 2010-11-11 800 40 840 

Bây giờ tôi ước tôi có thể nói điều này đã kết thúc và bỏ đi ... nhưng các vấn đề nhập dữ liệu tồn tại. Trong dòng 1 và 2, thời gian kết thúc của dòng 1 dòng lên với thời gian bắt đầu ở dòng 2 và cần được kết hợp để kết quả của tôi trông như thế này:

Date  Start length  end 

1 2010-11-11 600 70 670 

2 2010-11-11 750 15 765 

3 2010-11-11 800 40 840 

Bất cứ ý tưởng là làm thế nào để xây dựng logic này vì vậy tôi có được 3 dòng trở lại thay vì 4? Tôi đang làm việc để tự mình tham gia bảng trên # sd1.start + # sd1.length = # sd2.start ngay bây giờ.

Và để làm phức tạp hơn nữa ... ví dụ trên là 2 dòng cần kết hợp. Tôi đã đi qua một kỷ lục đã có 30 1 phút mục liên tiếp mà tôi sẽ cần phải thực hiện vào một kỷ lục duy nhất. May mắn là họ không thể chồng lên nhau (bạn sẽ không có 2 bản ghi trong cùng một phút), nhưng tôi không nghĩ rằng câu lệnh kết hợp mà tôi đang cân nhắc ở trên sẽ làm việc cho điều đó.

+0

Đã thực hiện một vài chỉnh sửa về ngữ pháp của riêng tôi ... có thêm một vài cột trong #SH, nhưng chúng không liên quan. – Twelfth

Trả lời

2

Không cần CTE, tất cả những gì bạn cần là bảng trợ giúp. Tạo ra nó một lần, như vậy:

Create Table DayMinute(Minute Integer) 
Declare @M Integer 
Set @M = 1 
While (@M <= 24*60) 
Begin 
    Insert Into DayMinute(Minute) Values(@M) 
    Set @M = @M + 1 
End 

Sau đó, tất cả bạn cần là một chút tricksiness:

Select 
    DM.Minute, 
    SD.Sched_ID 
Into #MinutesWithException 
From 
    DayMinute As DM 
    Inner Join #SD As SD 
    On DM.Minute Between SD.Start_Minute And SD.Start_Minute + Length 

Select 
    MWE.Sched_ID, 
    SH.[Date], 
    SH.Agent_ID, 
    [Start_Minute] = MWE.Minute, 
    [End_Minute] = (Select Min(Last.Minute) -- First one to have no successor 
        From #MinutesWithException As Last 
        Where Last.Sched_ID = MWE.Sched_ID 
        And Last.Minute > MWE.Minute 
        And Not Exists(Select * 
            From #MinutesWithException As Next 
            Where Next.Sched_ID = MWE.Sched_iD 
            And Next.Minute = Last.Minute + 1)) 
From 
    #MinutesWithException As MWE 
    Inner Join #SH As SH 
    On MWE.Sched_ID = SH.Sched_ID 
Where 
    Not Exists(Select * -- All those without predecessor 
      From #MinutesWithException As Previous 
      Where Previous.Sched_ID = MWE.Sched_ID 
       And Previous.Minute = MWE.Minute - 1) 

Hãy nhớ rằng, rất nhiều vấn đề SQL có thể được giải quyết bằng cách rephrasing họ. Đừng hỏi "phạm vi nào không có khoảng trống", hãy hỏi "phút nào có khoảng thời gian". Phần còn lại sau đó.

+0

Tôi đã suy nghĩ giống nhau trên Stu ... mới có phải là một cách thay thế để nhìn vào nó. Tôi đã phải thực hiện một vài sửa đổi để phù hợp với phần còn lại của kịch bản, tôi sẽ cho bạn biết làm thế nào nó đi. Và wow, bộ xử lý chuyên sâu. – Twelfth

+0

Điều đó thực sự hiệu quả hơn hay dễ đọc hơn? –

+0

Không chắc chắn về hiệu quả hơn ... nó ghim bộ vi xử lý của tôi ở 100% khi tôi chạy nó. Nó dường như làm các trick atleast, tôi tự hỏi làm thế nào nó sẽ phản ứng khi tôi ăn nó 20k hồ sơ thay vì 4 mặc dù .. – Twelfth

1

Nếu bạn sử dụng CTE đệ quy để kết hợp các kết quả truy vấn bạn có ở trên, bạn có thể kết hợp tối đa 32767 bản ghi với nhau. Bạn có thể xem xét cách tiếp cận đó nếu bạn không nghĩ mình sẽ nhận được gần số tiền đó.

Tôi đã tạo một ví dụ làm việc, bởi vì tôi không chắc chắn. Nhóm của bạn sẽ khác, nhưng đây là ý tưởng chung:

CREATE TABLE times 
(
[Date] datetime, 
[start] int, 
[length] int, 
[end] int 
) 
INSERT INTO times([Date], [Start], [length], [End]) 
VALUES ('11/11/2010',600,30,630) 
INSERT INTO times([Date], [Start], [length], [End]) 
VALUES ('11/11/2010',630,40,670) 
INSERT INTO times([Date], [Start], [length], [End]) 
VALUES ('11/11/2010',750,15,765) 
INSERT INTO times([Date], [Start], [length], [End]) 
VALUES ('11/11/2010',800,40,840) 

;WITH chaintimes AS 
(
    SELECT t1.Date, t1.start, t1.length, t1.[end] 
    FROM times t1 LEFT JOIN times t2 ON t1.start = t2.[end] 
    WHERE t2.[end] IS NULL 
    UNION ALL 
    SELECT times.Date, chaintimes.start, chaintimes.length + times.length AS length, times.[end] 
    FROM times INNER JOIN chaintimes ON times.start = chaintimes.[end] 
) 
, start_maxlength AS 
(
    SELECT date, start, max(length) AS maxlength 
    FROM chaintimes 
    group by date, start 
) 
SELECT * FROM chaintimes ct 
INNER JOIN start_maxlength ml 
ON ct.Date = ml.Date AND ct.start = ml.start AND ct.length = ml.maxlength 
+0

Tôi đã đề cập đến môi trường của tôi về điều này ... MSSQL 2000. Điều này có vẻ PL/SQL. Tôi sẽ thử, nhưng tôi nghi ngờ một lỗi. Tôi nghĩ rằng tôi hiểu logic bạn có ở đây ít nhất ... hãy để tôi cố gắng sửa đổi mã hiện tại của tôi bằng cách sử dụng kiểu logic này – Twelfth

+0

Ah, có CTE đã được giới thiệu trong MS SQL 2005, không cần phải bận tâm. –

+0

Mặc dù tôi mạnh mẽ không đồng ý rằng thiếu bối cảnh là một lý do chính đáng cho * downvote *. –