Helpex - Trao đổi & giúp đỡ Đăng nhập
13

Tôi có một bảng T1, nó chứa giá trị TÊN (không phải là duy nhất) và phạm vi ngày (D1 và D2 ​​là ngày) Khi TÊN giống nhau, chúng tôi tạo một liên hợp các phạm vi ngày (ví dụ B).

Nhưng kết quả là (X), chúng ta cần tạo giao điểm của tất cả các phạm vi ngày

Chỉnh sửa: Bảng T1

NAME | D1       | D2
A    | 20100101 | 20101211
B    | 20100120 | 20100415
B    | 20100510 | 20101230
C    | 20100313 | 20100610

Kết quả :

X    | 20100313 | 20100415
X    | 20100510 | 20100610

Về mặt trực quan, điều này sẽ cung cấp những điều sau:

NAME        : date range
A           : [-----------------------]-----
B           : --[----]----------------------
B           : ----------[---------------]---
C           : -----[--------]---------------

Kết quả :

X           : -----[-]----------------------
X           : ----------[---]---------------

Bất kỳ ý tưởng làm thế nào để có được điều đó bằng cách sử dụng SQL / PL SQL?

13 hữu ích 5 bình luận 10k xem chia sẻ
8

đây là một giải pháp nhanh chóng (có thể không hiệu quả nhất):

SQL> CREATE TABLE myData AS
  2  SELECT 'A' name, date'2010-01-01' d1, date'2010-12-11' d2 FROM DUAL
  3  UNION ALL SELECT 'B', date'2010-01-20', date'2010-04-15' FROM DUAL
  4  UNION ALL SELECT 'B', date'2010-05-10', date'2010-12-30' FROM DUAL
  5  UNION ALL SELECT 'C', date'2010-03-13', date'2010-06-10' FROM DUAL;

Table created

SQL> WITH segments AS (
  2  SELECT dat seg_low, lead(dat) over(ORDER BY dat) seg_high
  3    FROM (SELECT d1 dat FROM myData
  4           UNION
  5           SELECT d2 dat FROM myData)
  6  )
  7  SELECT s.seg_low, s.seg_high
  8    FROM segments s
  9    JOIN myData m ON s.seg_high > m.d1
 10                 AND s.seg_low < m.d2
 11   GROUP BY s.seg_low, s.seg_high
 12  HAVING COUNT(DISTINCT NAME) = 3;

SEG_LOW     SEG_HIGH
----------- -----------
13/03/2010  15/04/2010
10/05/2010  10/06/2010

Tôi xây dựng tất cả các phạm vi ngày liên tiếp có thể có và kết hợp "lịch" này với dữ liệu mẫu. Điều này sẽ liệt kê tất cả các phạm vi có 3 giá trị. Bạn có thể cần hợp nhất kết quả nếu bạn thêm các hàng:

SQL> insert into mydata values ('B',date'2010-04-15',date'2010-04-16');

1 row inserted

SQL> WITH segments AS (
  2  SELECT dat seg_low, lead(dat) over(ORDER BY dat) seg_high
  3    FROM (SELECT d1 dat FROM myData
  4           UNION
  5           SELECT d2 dat FROM myData)
  6  )
  7  SELECT MIN(seg_low), MAX(seg_high)
  8    FROM (SELECT seg_low, seg_high, SUM(gap) over(ORDER BY seg_low) grp
  9             FROM (SELECT s.seg_low, s.seg_high,
 10                           CASE
 11                              WHEN s.seg_low
 12                                   = lag(s.seg_high) over(ORDER BY s.seg_low)
 13                              THEN 0
 14                              ELSE 1
 15                           END gap
 16                      FROM segments s
 17                      JOIN myData m ON s.seg_high > m.d1
 18                                   AND s.seg_low < m.d2
 19                     GROUP BY s.seg_low, s.seg_high
 20                    HAVING COUNT(DISTINCT NAME) = 3))
 21   GROUP BY grp;

MIN(SEG_LOW) MAX(SEG_HIGH)
------------ -------------
13/03/2010   16/04/2010
10/05/2010   10/06/2010
8 hữu ích 3 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ sql oracle plsql date-range date-arithmetic , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading