2009-03-11 6 views
44

Ho una tabella come questa:Come ottenere la differenza tra due righe per un campo colonna?

valori rowInt
rowInt Value 
2  23 
3  45 
17  10 
9  0 
.... 

La colonna sono interi ma non in sequenza con la stessa increament. Posso utilizzare il seguente SQL per elencare i valori per rowInt:

valori della lista
SELECT * FROM myTable ORDER BY rowInt; 

Questo sarà da rowInt. Come si può ottenere ottenere la differenza di valore tra i due file con il risultato come questo:

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

Il tavolo è in SQL 2005 (Miscrosoft)

+0

È inteso che hai 10-45 nella seconda fila? Da dove prendi un 10? – Quassnoi

+0

alcuni calc non sono coerenti ... row2 (45-23) è row3-row2, ma row9 (0-45) è row9-row3, non dovrebbe essere (10-0) che è row17-row9? – MatBailie

+0

Sembra che si voglia contare la differenza tra i valori adiacenti nel set di righe originale (2, 3, 17, 9). Quindi dovrò chiederti: qual è la colonna su cui è ordinato il set di righe ORIGINALE? Ricorda che non esiste alcuna cosa come "ordinamento predefinito" in SQL. – Quassnoi

risposta

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: Ci sto pensando, utilizzando una subquery nella selezione (ala Quassnoi's answer) potrebbe essere più efficiente. Vorrei provare diverse versioni e guardare i piani di esecuzione per vedere quale avrebbe prestazioni migliori sulla dimensione del set di dati che hai ...

+0

Se ha un indice su rowInt (che penso che faccia), la mia query è più efficiente. Se non lo fa, allora il tuo è (se è possibile parlare di efficienza in questo caso). Guarda qui per i dettagli: http: // StackOverflow.it/questions/590079/for-autoincrement-fields-maxid-vs-top-1-id-order-by-id-desc – Quassnoi

+0

Ho creato una tabella fittizia con 1 milione di record creati casualmente e ho scoperto che entrambe le query richiedevano lo stesso tempo . In effetti l'unica differenza nei piani di esecuzione era la posizione di una funzione SORT (ho ordinato l'output finale) – MatBailie

+0

Mi piace il tuo metodo. Funziona bene con il mio caso. –

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

Se vuoi essere sicuro degli ordini, usa "Row_Number()" e confrontare il prossimo record di record corrente (date un'occhiata da vicino "sulla" clausola)

T1.ID + 1 = T2.ID 

Tu sei fondamentalmente unendo riga successiva con riga corrente, senza specificare "min" o fare "top". Se si dispone di un numero limitato di record, altre soluzioni di "Dems" o "Quassanoi" funzioneranno correttamente.

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

SQL Server supporta le funzioni analitiche?

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

Msg 195, livello 15, stato 10, riga 3 'ritardo' non è un nome funzione predefinito riconosciuto. – Sung

+0

Ho dato questo punto perché sì Denali fa ... anche se forse SQL Server non ha fatto quando è stata postata questa risposta – Pixelated

+1

@FairFunk Ho sottratto un punto perché la domanda è taggata nel 2005 quindi la funzionalità di Denali è irrilevante. –

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 per trovare la differenza data fra 2 file di una singola colonna

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

Questa è una domanda molto vecchia e la tua risposta in realtà non risponde alla stessa domanda posta. – shawnt00

2

SQL Server 2012 e il supporto LAG/LEAD funzioni per accedere alla riga precedente o successiva. SQL Server 2005 non supporta questo (in SQL2005 è necessario un join o altro).

Uno SQL 2012 esempio di questi dati

/* 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 

PIOMBO (valore) restituisce il valore della riga successiva rispetto all'ordine proposta in "over" clausola.

+1

LAG. Non LAD. Non mi permetterà di modificare perché devi modificare 6 caratteri – danmiser

Problemi correlati