2009-03-11 39 views
44

Tôi có một bảng như thế này:Làm cách nào để có được sự khác biệt giữa hai hàng cho một trường cột?

giá trị rowInt
rowInt Value 
2  23 
3  45 
17  10 
9  0 
.... 

Cột là số nguyên nhưng không phải trong một chuỗi với cùng increament. Tôi có thể sử dụng sql sau để liệt kê các giá trị theo rowInt:

SELECT * FROM myTable ORDER BY rowInt; 

Điều này sẽ liệt kê các giá trị theo rowInt. Làm thế nào có thể nhận được sự khác biệt của giá trị gia tăng giữa hai hàng với kết quả như thế này:

rowInt Value Diff 
2  23 22 --45-23 
3  45 -35 --10-45 
9  0  -45 --0-45 
17  10 10 -- 10-0 
.... 

Bảng này là trong SQL 2005 (Miscrosoft)

+0

Có dự định bạn có 10-45 ở hàng thứ hai không? Bạn lấy 10 từ đâu? – Quassnoi

+0

một số calcs không nhất quán ... row2's (45-23) là row3-row2, nhưng row9's (0-45) là row9-row3, có nên không (10-0) là row17-row9 không? – MatBailie

+0

Có vẻ như bạn muốn tính sự khác biệt giữa các giá trị liền kề trong các hàng ban đầu của bạn (2, 3, 17, 9). Sau đó, tôi sẽ phải hỏi bạn: cột hàng ORIGINAL của bạn được sắp xếp là gì? Hãy nhớ rằng không có thứ như 'thứ tự mặc định' trong SQL. – Quassnoi

Trả lời

46
SELECT 
    [current].rowInt, 
    [current].Value, 
    ISNULL([next].Value, 0) - [current].Value 
FROM 
    sourceTable  AS [current] 
LEFT JOIN 
    sourceTable  AS [next] 
     ON [next].rowInt = (SELECT MIN(rowInt) FROM sourceTable WHERE rowInt > [current].rowInt) 

EDIT: Suy nghĩ về nó, sử dụng một truy vấn phụ trong lựa chọn (câu trả lời của ala Quassnoi) có thể hiệu quả hơn. Tôi sẽ dùng thử các phiên bản khác nhau và xem các kế hoạch thực hiện để xem cái nào sẽ hoạt động tốt nhất trên kích thước của bộ dữ liệu mà bạn có ...

+0

Nếu anh ta có chỉ mục trên rowInt (mà tôi nghĩ anh ấy làm) thì truy vấn của tôi hiệu quả hơn. Nếu anh ta không, thì người của bạn là (nếu có thể nói về hiệu quả trong trường hợp này). Nhìn ở đây để biết chi tiết: http: // stackoverflow.com/questions/590079/for-autoincrement-fields-maxid-vs-top-1-id-order-by-id-desc – Quassnoi

+0

Tôi đã tạo một bảng giả với 1 triệu bản ghi được tạo ngẫu nhiên và nhận thấy rằng cả hai truy vấn đều mất cùng một thời gian . Trong thực tế, sự khác biệt duy nhất trong kế hoạch thực hiện là vị trí của một hàm SORT (tôi đã sắp xếp đầu ra cuối cùng) – MatBailie

+0

Tôi thích phương pháp của bạn. Nó hoạt động tốt với trường hợp của tôi. –

21
SELECT rowInt, Value, 
     COALESCE(
     (
     SELECT TOP 1 Value 
     FROM myTable mi 
     WHERE mi.rowInt > m.rowInt 
     ORDER BY 
      rowInt 
     ), 0) - Value AS diff 
FROM myTable m 
ORDER BY 
     rowInt 
10

Nếu bạn thực sự muốn chắc chắn về đơn đặt hàng, hãy sử dụng "Row_Number()" và so sánh kỷ lục tiếp theo của bản ghi hiện tại (có một cái nhìn cận cảnh "về" khoản)

T1.ID + 1 = T2.ID 

Bạn đang cơ bản khi tham gia hàng tiếp theo với hàng hiện tại, mà không chỉ định "min" hay làm "top". Nếu bạn có một số lượng nhỏ các bản ghi, các giải pháp khác của "Dems" hoặc "Quassanoi" sẽ hoạt động tốt.

with T2 as (
    select ID = ROW_NUMBER() over (order by rowInt), 
      rowInt, Value 
    from myTable 
) 
select T1.RowInt, T1.Value, Diff = IsNull(T2.Value, 0) - T1.Value 
from ( SELECT ID = ROW_NUMBER() over (order by rowInt), * 
      FROM myTable) T1 
     left join T2 on T1.ID + 1 = T2.ID 
ORDER BY T1.ID 
2

Máy chủ SQL có hỗ trợ chức năng phân tích không?

select rowint, 
     value, 
     value - lag(value) over (order by rowint) diff 
from  myTable 
order by rowint 
/
+0

Msg 195, Cấp 15, Tiểu bang 10, Dòng 3 'lag' không phải là tên hàm được tích hợp sẵn. – Sung

+0

Tôi đã đưa ra một điểm vì có Denali không ... mặc dù có thể máy chủ sql không khi câu trả lời này được đăng – Pixelated

+1

@ FairFunk Tôi đã trừ một điểm vì câu hỏi được gắn thẻ 2005 để chức năng Denali không liên quan. –

0
select t1.rowInt,t1.Value,t2.Value-t1.Value as diff 
from (select * from myTable) as t1, 
    (select * from myTable where rowInt!=1 
     union all select top 1 rowInt=COUNT(*)+1,Value=0 from myTable) as t2 
where t1.rowInt=t2.rowInt-1 
0

Query để tìm sự khác biệt ngày giữa 2 hàng của một cột duy nhất

SELECT 
Column name, 
DATEDIFF(
(SELECT MAX(date) FROM table name WHERE Column name < b. Column name), 
Column name) AS days_since_last 
FROM table name AS b 
+0

Đây là một câu hỏi rất cũ và câu trả lời của bạn không thực sự trả lời cùng một câu hỏi đặt ra. – shawnt00

2

SQL Server 2012 và lên hỗ trợ LAG/LEAD chức năng để truy cập hàng trước hoặc sau này. SQL Server 2005 không hỗ trợ điều này (trong SQL2005 bạn cần một tham gia hoặc cái gì khác).

Một SQL 2012 Ví dụ trên dữ liệu này

/* Prepare */ 
select * into #tmp 
from 
(
    select 2 as rowint,  23 as Value 
    union select 3,  45 
    union select 17,  10 
    union select 9,  0 
) x 


/* The SQL 2012 query */ 
select rowInt, Value, LEAD(value) over (order by rowInt) - Value 
from #tmp 

LEAD (giá trị) sẽ trả về giá trị của các hàng tiếp theo đối với trật tự được đưa ra trong "qua" khoản.

+1

LAG. Không phải LAD. Nó sẽ không cho phép tôi chỉnh sửa vì bạn phải thay đổi 6 ký tự – danmiser

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