2013-08-15 25 views
7

Có lẽ có một giải pháp khá đơn giản cho vấn đề của tôi, nhưng tôi đang gặp khó khăn khi xây dựng một cụm từ tìm kiếm tốt cho nó. Tôi có một bảng có chứa dấu thời gian và số lượng:Tìm sự gián đoạn từ một bảng SQL

2013-08-15 14:43:58.447 5 
2013-08-15 14:44:58.307 12 
2013-08-15 14:45:58.383 14 
2013-08-15 14:46:58.180 0 
2013-08-15 14:47:58.210 4 
2013-08-15 14:48:58.287 6 
2013-08-15 14:49:58.550 12 
2013-08-15 14:50:58.440 2 
2013-08-15 14:51:58.390 5 

Như bạn có thể thấy, số lần tăng và sau đó được làm trống một lần trong một thời gian. Tìm kiếm các hàng mà count = 0 rất dễ, nhưng đôi khi số đếm được tăng lên trước khi số không được ghi lại. Vào lúc 14:49 đếm là 12, sau đó nó được đặt lại về 0 và tăng lên 2 trước lần đăng nhập tiếp theo lúc 14:50.

tôi cần phải liệt kê các timestamps nơi số lượng ít hơn so với số trước:

2013-08-15 14:46:58.180 0 
2013-08-15 14:50:58.440 2 

tôi bắt đầu để thực hiện một tham gia vào bảng riêng của mình, để so sánh hai hàng nhưng SQL sớm trở nên rất lộn xộn.

+0

Nếu bạn có thể đặt chúng trong một bảng với một chỉ số trong đúng thứ tự, việc tham gia phải rất đơn giản. –

+0

Bảng được lập chỉ mục trên dấu thời gian, nhưng tôi thực sự không thể nhìn thấy giải pháp đơn giản. – Anlo

+0

Thêm một bảng nơi dòng 1 có số 1 và dòng 2 có số 2 vv. Sau đó, bạn chỉ có thể chọn vị trí 'T2.id = T1.id + 1' và' T2.num

Trả lời

5

Cũng trong trường hợp này bạn có thể sử dụng LEAD() chức năng:

with CTE as 
(
select t.*, LEAD(ct) OVER (ORDER BY dt DESC) as LEAD_CT from t 
) 
select dt,ct from CTE where LEAD_CT>CT 

SQLFiddle demo

UPD: LEAD() có sẵn từ phiên bản SQLServer 2012. Năm 2008 bạn có thể thay thế nó bằng một subquery:

select * 
     FROM T as T1 
     where (SELECT TOP 1 ct FROM T 
          WHERE T.dt<T1.DT 
          ORDER BY dt DESC) >CT 

SQLFiddle demo

+2

Không phải trong SQL 2008 bạn không thể. – podiluska

+2

Nhưng, tuy nhiên, một tính năng tốt đẹp để có trong MSSQL2012! Cảm ơn bạn đã cho chúng tôi xem. ;-) – cars10m

+0

@podiluska: Bạn nói đúng. Xin lỗi tôi đã bỏ lỡ "sql-server-2008" tag :( – valex

9

Điều này có nghĩa là nó tạo ra một số hàng dựa trên cột ts (datetime), sau đó nó dễ dàng hơn để tham gia vào mục trước đó. Sau đó nó so sánh thời gian và số lượng để tìm các ngoại lệ.

;with cte as 
(
    select * , 
     ROW_NUMBER() over (order by ts) rn  
    from yourtable 
) 
    select c1.* from cte c1 
     inner join cte c2 
      on c1.rn=c2.rn+1 
      and c1.c < c2.c 
+0

Tôi thực sự sẽ không so sánh các ts và thay vào đó, hãy thêm số làm đối số sắp xếp thứ hai (giảm) vì người ta có thể xem xét 2 giá trị đếm ở cùng một ts là một sự bất thường. –

1

Sử dụng ROW_NUMBER() chức năng bạn có thể gán số trên đơn đặt hàng và sử dụng chúng cho tham gia:

WITH CTE_RN AS 
(
    SELECT *, ROW_NUMBER() OVER (ORDER BY [TimeStamp]) RN 
    FROM Table1 
) 
SELECT r2.* 
FROM CTE_RN r1 
    INNER JOIN CTE_RN r2 ON r1.RN +1 = r2.RN 
WHERE r1.count > r2.count 

SQLFiddle DEMO