Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

MySQL an toàn các hàng trong bảng với các khoảng ngày chồng chéo

Một cách để làm điều đó là sử dụng các truy vấn con tương quan:

SELECT DISTINCT
       (SELECT MIN(opens)
       FROM mytable AS t2
       WHERE t2.opens <= t1.closes AND t2.closes >= t1.opens) AS start,
       (SELECT MAX(closes)
       FROM mytable AS t2
       WHERE t2.opens <= t1.closes AND t2.closes >= t1.opens) AS end       
FROM mytable AS t1
ORDER BY opens

WHERE các vị từ của các truy vấn con tương quan:

t2.opens <= t1.closes AND t2.closes >= t1.opens

trả lại tất cả các bản ghi chồng chéo liên quan đến bản ghi hiện tại. Thực hiện tổng hợp một trong những bản ghi này, chúng ta có thể tìm thấy ngày bắt đầu / ngày kết thúc của mỗi khoảng thời gian:ngày bắt đầu của khoảng thời gian là ngày opens tối thiểu ngày giữa tất cả các bản ghi chồng chéo, trong khi ngày kết thúc là ngày closes tối đa ngày tháng.

Demo tại đây

CHỈNH SỬA:

Giải pháp trên sẽ không hoạt động với một tập hợp các khoảng thời gian như sau:

1. |-----------|
2. |----|
3.           |-----|

Ghi không. 2, khi được xử lý, sẽ tạo ra khoảng thời gian bắt đầu / kết thúc thiếu sót.

Đây là một giải pháp sử dụng các biến:

SELECT MIN(start) AS start, MAX(end) AS end
FROM (
  SELECT @grp := IF(@start = '1900-01-01' OR 
                   (opens <= @end AND closes >= @start), @grp, @grp+1) AS grp,        
         @start := IF(@start = '1900-01-01', opens, 
                      IF(opens <= @end AND closes >= @start, 
                         IF (@start < opens, @start, opens), opens)) AS start,
         @end := IF(@end = '1900-01-01', closes, 
                    IF (opens <= @end AND closes >= @start, 
                      IF (@end > closes, @end, closes), closes)) AS end                 
  FROM mytable
  CROSS JOIN (SELECT @grp := 1, @start := '1900-01-01', @end := '1900-01-01') AS vars
  ORDER BY opens, DATEDIFF(closes, opens) DESC) AS t
GROUP BY grp

Ý tưởng là bắt đầu từ opens/closes ngoài cùng bên trái khoảng thời gian. Các biến @start , @end được sử dụng để truyền khoảng thời gian hợp nhất mở rộng dần dần (khi các hàng chồng chéo mới đang được xử lý) xuống chuỗi khoảng thời gian. Sau khi gặp phải khoảng thời gian không trùng lặp, [@start - @end] được khởi tạo để khớp với khoảng thời gian mới này và grp được tăng lên một.

Demo tại đây




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hibernate @Enumerated dường như bị bỏ qua

  2. Tạo trình kích hoạt để cập nhật cột sắp xếp / thứ tự

  3. MySQL Workbench là gì?

  4. Cách tốt nhất để chọn động tên bảng trong thời gian chạy là gì?

  5. Hàm MySQL LEAST () - Tìm đối số nhỏ nhất trong danh sách đối số