2013-01-11 46 views
5

Tôi có một bảng tương tự như dưới đây trong MS SQL Server.Tối thiểu và tối đa theo ID trong nhóm và điều kiện khác

 id | Timestamp | active 
    -----+-----------+-------- 
     1 | 1:00 | 1 
     1 | 2:00 | 1 
     1 | 3:00 | 1 
     1 | 4:00 | 0 
     1 | 5:00 | 0 
     1 | 6:00 | 1 
     1 | 7:00 | 0 
     1 | 8:00 | 0 
     1 | 9:00 | 0 
     1 | 10:00 | 1 
     1 | 11:00 | 1 
     1 | 12:00 | 0 
     1 | 13:00 | 1 
     2 | 2:00 | 1 
     2 | 3:00 | 1 
     2 | 4:00 | 0 
     2 | 5:00 | 0 
     3 | 8:00 | 0 
     3 | 9:00 | 0 
     4 | 1:00 | 1 
     4 | 2:00 | 1 
     5 | 16:00 | 0 

Điều tôi muốn tìm hiểu khi mỗi ID không hoạt động (active = 0) trong bao lâu. Những gì tôi đã cố gắng làm là nhóm nó theo id khi active = 0, và làm một dateiff vào thời gian min và max. Nhưng điều đó sẽ cho tôi một kết quả cho id 1 cho biết nó đã được diễn ra trong 8 giờ (12:00 - 4:00) @ 12:00. Khi tôi thực sự muốn là một truy vấn sẽ cho tôi tập hợp kết quả sau.

id | approx. offline in hours | at time 
    ---+--------------------------+----------- 
    1 |   1    | 5:00 
    1 |   2    | 9:00 
    1 |   0    | 12:00 
    2 |   1    | 5:00 
    3 |   0    | 9:00 
    5 |   0    | 16:00 

Truy vấn sai tôi ban đầu đã cố gắng là

SELECT id as [Inactive], 
     DATEDIFF(hour, MIN(Timestamp), MAX(Timestamp)) as [approx. offline in hours], 
     MAX(Timestamp) as [at time] 
FROM table 
WHERE active = 0 
GROUP BY [Inactive] 

Nhưng vấn đề với truy vấn mà là nó bỏ qua lần kích hoạt ở giữa. Tôi đã xem xét THIS câu hỏi đã được hỏi và trả lời bằng PARTITION, nhưng có vẻ như câu hỏi là đủ khác và câu trả lời quá cụ thể đối với câu hỏi mà tôi không thể hiểu được.

Mọi trợ giúp đều được đánh giá cao.

+0

bạn đang sử dụng rdbms nào? sql-server, oracle? – Taryn

+0

@bluefeet Dấu ngoặc vuông nhiều khả năng == SQL Server –

+0

@JoachimIsaksson Tôi đồng ý nhưng họ nên nêu rõ thứ họ đang sử dụng. – Taryn

Trả lời

3

Một cách để tiếp cận điều này, hoạt động trong bất kỳ cơ sở dữ liệu nào, là sử dụng truy vấn con tương quan. Ý tưởng là gán một tên nhóm cho mỗi chuỗi giá trị hoạt động liên tiếp. Tên nhóm cụ thể là thời điểm thay đổi tiếp theo trong giá trị.

select id, active, min(TimeStamp), max(TimeStamp) 
from (select t.*, 
      (select min(timeStamp) from t t2 where t2.id = t.id and t2.timeStamp > t.timeStamp and t2.active <> t.active 
      ) groupName 
     from t 
    ) t 
group by id, groupName, active 

Hãy cẩn thận cách bạn nhận dấu thời gian theo thời lượng tùy thuộc vào cơ sở dữ liệu. Vì bạn không chỉ định cơ sở dữ liệu, tôi sẽ cho phép bạn thêm logic đó.

Ngoài ra, nếu bản ghi cuối cùng cho id đã cho không hoạt động, tên nhóm là NULL. Đó không phải là vấn đề.

+0

Tôi nghĩ rằng có một lỗi trong câu trả lời này, vì tên nhóm sẽ là NULL khi ID thay đổi – Bulat

+0

@Bulat. . . Đó không phải là vấn đề. NULL là hợp lệ để nhóm và id được bao gồm trong cột 'nhóm bởi'. –

+0

Có, bạn nói đúng, nó không phải là một vấn đề. Bạn có thể chỉ muốn đổi tên TimesStamp thành thời gian để làm cho các tên trường nhất quán. http://sqlfiddle.com/#!3/e5831/45/0 – Bulat

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