2009-06-22 46 views
6

tôi đã thiết lập sau ngày (dd/MM/yyyy) phù hợp với các sự kiện trong cơ sở dữ liệu của tôi:Tính phạm vi ngày mất tích và phạm vi ngày chồng chéo giữa hai ngày

 
eventId  startDate  endDate 
1   02/05/2009 10/05/2009 
2   08/05/2009 12/05/2009 
3   10/05/2009 12/05/2009 
4   21/05/2009 21/05/2009 
5   25/05/2009 NULL 
6   01/06/2009 03/06/2009 

Các sự kiện có một khởi đầu và ngày kết thúc (thời gian không quan trọng) và một endDate NULL có nghĩa là sự kiện vẫn đang được tiến hành.

Điều tôi muốn xác định là phạm vi ngày giữa hai ngày tùy ý trong đó có a) không có sự kiện và b) sự kiện trùng lặp.

Vì vậy, đối với một phạm vi ngày đầu vào của 01/04/2009 - 30/06/2009 tôi mong chờ để có kết quả như sau:

 
no event: 01/04/2009 - 01/05/2009 
overlap : 08/05/2009 - 10/05/2009 
overlap : 10/05/2009 - 12/05/2009 
no event: 13/05/2009 - 20/05/2009 
no event: 22/05/2009 - 24/05/2009 
overlap : 01/06/2009 - 03/06/2009 

Lưu ý rằng hai dãy chồng chéo liền kề sẽ được chấp nhận như là một kết quả.

Mọi người có thể giúp tôi với thuật toán SQL để tạo tập hợp kết quả này không?

EDIT: Cơ sở dữ liệu nền tảng mục tiêu là SQL Server 2005. Ngày được ghi là 10/05/2009 00:00:00, có nghĩa là sự kiện đã kết thúc vào khoảng thời gian từ ngày 10/5/2009 00:00:00 và 10/5/2009 23:59:59. Điều này cũng đúng cho những ngày bắt đầu. Do đó, phạm vi ngày đầu vào cũng có thể được đọc là 01/04/2009 00:00:00 - 30/06/2009 23:59:59.

+1

On mà nền tảng cơ sở dữ liệu (s), bạn sẽ được chạy truy vấn này? –

Trả lời

4

Đó là một sự thay đổi nhỏ của các chức năng để làm phẳng timespans giao nhau trong SQL Server:

Đó là một trong những trường hợp hiếm hoi khi con trỏ dựa trên cách tiếp cận trong SQL Server là nhanh hơn một set-based one:


CREATE FUNCTION mytable(@p_from DATETIME, @p_till DATETIME) 
RETURNS @t TABLE 
     (
     q_type VARCHAR(20) NOT NULL, 
     q_start DATETIME NOT NULL, 
     q_end DATETIME NOT NULL 
     ) 
AS 
BEGIN 
     DECLARE @qs DATETIME 
     DECLARE @qe DATETIME 
     DECLARE @ms DATETIME 
     DECLARE @me DATETIME 
     DECLARE cr_span CURSOR FAST_FORWARD 
     FOR 
     SELECT startDate, endDate 
     FROM mytable 
     WHERE startDate BETWEEN @p_from AND @p_till 
     ORDER BY 
       startDate 
     OPEN cr_span 
     FETCH NEXT 
     FROM cr_span 
     INTO @qs, @qe 
     SET @ms = @qs 
     SET @me = @qe 
     WHILE @@FETCH_STATUS = 0 
     BEGIN 
       FETCH NEXT 
       FROM cr_span 
       INTO @qs, @qe 
       IF @qs > @me 
       BEGIN 
         INSERT 
         INTO @t 
         VALUES ('overlap', @ms, @me) 
         INSERT 
         INTO @t 
         VALUES ('gap', @me, @qs) 
         SET @ms = @qs 
       END 
       SET @me = CASE WHEN @qe > @me THEN @qe ELSE @me END 
     END 
     IF @ms IS NOT NULL 
     BEGIN 
       INSERT 
       INTO @t 
       VALUES (@ms, @me) 
     END 
     CLOSE cr_span 
     RETURN 
END 
GO 

Chức năng này nén từng bộ tiếp giáp của các dải giao nhau thành một phạm vi và trả về cả dải ô và khoảng trống sau.

+0

Câu trả lời của Quassnoi có phải là giải pháp cho vấn đề không? nếu vậy tên của bảng dữ liệu trong hàm là gì. –

+0

+1 Cảm ơn ....... –

1

Nếu không thực sự hiểu những gì vấn đề bạn đang cố gắng để giải quyết, đây là giải pháp của tôi để một số vấn đề ra khỏi đỉnh đầu của tôi:

  1. Tạo hàm bảng (UDF) "tất cả-ngày" mà có thể trả lại tất cả các ngày trong một năm.
  2. Chuyển đổi sự kiện của bạn thành các ngày riêng biệt (một hàng sự kiện sẽ trở thành nhiều hàng vì có ngày trong đó) bằng các sự kiện nối bên trong với tất cả ngày where the date is between event's start and end dates ... Giữ lại sự kiện ban đầuId.
  3. Thực hiện kết hợp bên ngoài của ngày sự kiện với tất cả các ngày (một lần nữa) để tìm khoảng trống hoặc bỏ sót.
  4. Tham gia ngày sự kiện với chính mình trên where dates are same but eventId is not để tìm chồng chéo.
0

nghèo, với postgresql, bạn có thể làm điều đó chỉ đơn giản là tôi:

(start1, END1) chồng chéo (START2, end2) (start1, length1) chồng chéo (START2, length2)

sản lượng biểu hiện này đúng khi hai khoảng thời gian (được xác định bởi điểm cuối của chúng) trùng lặp, sai khi chúng không trùng lặp. Các điểm cuối có thể được xác định là cặp ngày tháng, thời gian hoặc dấu thời gian; hoặc là ngày, thời gian hoặc dấu thời gian được theo sau bởi một khoảng thời gian.

CHỌN (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); Kết quả: đúng CHỌN (DATE '2001-02-16', INTERVAL '100 ngày') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); Kết quả: false

nhưng dưới sql server, tôi không biết ... xin lỗi

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