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

Tạo các nhóm ngày liên tiếp đáp ứng một tiêu chí nhất định

Trong câu trả lời này, tôi sẽ giả sử rằng trường "id" đánh số các hàng liên tục khi được sắp xếp theo ngày tăng dần, giống như trong dữ liệu ví dụ. (Có thể tạo một cột như vậy nếu nó không tồn tại).

Đây là ví dụ về kỹ thuật được mô tả tại đây tại đây .

1) Tham gia bảng với chính nó trên các giá trị "id" liền kề. Điều này ghép nối các hàng liền kề. Chọn các hàng có trường "phân bổ" đã thay đổi. Lưu trữ kết quả trong một bảng tạm thời, đồng thời giữ một chỉ mục đang chạy.

SET @idx = 0;
CREATE TEMPORARY TABLE boundaries
SELECT
   (@idx := @idx + 1) AS idx,
   a1.date AS prev_end,
   a2.date AS next_start,
   a1.allocation as allocation
FROM allocations a1
JOIN allocations a2
ON (a2.id = a1.id + 1)
WHERE a1.allocation != a2.allocation;

Điều này cung cấp cho bạn một bảng có "cuối kỳ trước", "đầu kỳ tiếp theo" và "giá trị của" phân bổ "trong kỳ trước" trong mỗi hàng:

+------+------------+------------+------------+
| idx  | prev_end   | next_start | allocation |
+------+------------+------------+------------+
|    1 | 2012-01-01 | 2012-01-02 |          0 |
|    2 | 2012-01-02 | 2012-01-03 |          2 |
|    3 | 2012-01-05 | 2012-01-06 |          0 |
+------+------------+------------+------------+

2) Chúng ta cần bắt đầu và kết thúc mỗi kỳ trong cùng một hàng, vì vậy chúng ta cần kết hợp các hàng liền kề lại. Thực hiện việc này bằng cách tạo một bảng tạm thời thứ hai như boundaries nhưng có idx trường 1 lớn hơn:

+------+------------+------------+
| idx  | prev_end   | next_start |
+------+------------+------------+
|    2 | 2012-01-01 | 2012-01-02 |
|    3 | 2012-01-02 | 2012-01-03 |
|    4 | 2012-01-05 | 2012-01-06 |
+------+------------+------------+

Bây giờ hãy tham gia trên idx và chúng tôi nhận được câu trả lời:

SELECT
  boundaries2.next_start AS start,
  boundaries.prev_end AS end,
  allocation
FROM boundaries
JOIN boundaries2
USING(idx);

+------------+------------+------------+
| start      | end        | allocation |
+------------+------------+------------+
| 2012-01-02 | 2012-01-02 |          2 |
| 2012-01-03 | 2012-01-05 |          0 |
+------------+------------+------------+

** Lưu ý rằng câu trả lời này nhận đúng khoảng thời gian "nội bộ" nhưng bỏ sót hai khoảng thời gian "cạnh" trong đó phân bổ =0 ở đầu và phân bổ =5 ở cuối. Chúng có thể được lấy bằng UNION nhưng tôi muốn trình bày ý tưởng cốt lõi mà không phức tạp.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Microsoft công bố SQL Server 2012 R2 và SQL Server 2012 R3!

  2. Cách lưu trữ bản ghi lịch sử trong bảng lịch sử trong SQL Server

  3. Cách định dạng ngày và giờ trong SQL Server

  4. SQL Server 2008, mệnh đề WHERE khác nhau với một truy vấn

  5. Chuỗi định dạng ngày / giờ tùy chỉnh được hỗ trợ bởi FORMAT () trong SQL Server