wake-up-neo.net

Wie bekomme ich den Unterschied zwischen zwei Zeilen für ein Spaltenfeld?

Ich habe einen Tisch wie diesen:

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

Die Werte der Spalte rowInt sind ganzzahlig, jedoch nicht in einer Sequenz mit derselben Erhöhung. Ich kann die folgende SQL verwenden, um Werte nach rowInt aufzulisten:

SELECT * FROM myTable ORDER BY rowInt;

Dadurch werden die Werte nach rowInt aufgelistet. Wie kann man die Differenz zwischen zwei Zeilen mit folgendem Ergebnis erhalten:

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

Die Tabelle ist in SQL 2005 (Miscrosoft)

51
David.Chu.ca
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)

BEARBEITEN: Wenn man darüber nachdenkt, kann die Verwendung einer Unterabfrage in der Auswahl (ala Quassnois Antwort) effizienter sein. Ich probiere verschiedene Versionen aus und schaue mir die Ausführungspläne an, um herauszufinden, welche die beste Größe für die Datenmenge sind, die Sie haben ...

54
MatBailie
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
24
Quassnoi

Wenn Sie wirklich sicher sein wollen, dass Sie Bestellungen haben, verwenden Sie "Row_Number ()" und vergleichen Sie den nächsten Datensatz des aktuellen Datensatzes (schauen Sie sich die "on" -Klausel an).

T1.ID + 1 = T2.ID

Sie schließen sich der nächsten Zeile mit der aktuellen Zeile an, ohne "min" anzugeben oder "oben" zu tun. Wenn Sie nur wenige Datensätze haben, funktionieren andere Lösungen von "Dems" oder "Quassanoi" gut.

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
11
Sung M. Kim

SQL Server 2012 und höher unterstützt die Funktionen LAG / LEAD für den Zugriff auf die vorherige oder nachfolgende Zeile. SQL Server 2005 unterstützt dies nicht (in SQL2005 benötigen Sie einen Join oder etwas anderes).

Ein SQL 2012-Beispiel zu diesen Daten

/* 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 (value) gibt den Wert der nächsten Zeile in Bezug auf die angegebene Reihenfolge in der "over" -Klausel zurück. 

8
Ansonmus

Unterstützt SQL Server Analysefunktionen?

select   rowint,
         value,
         value - lag(value) over (order by rowint) diff
from     myTable
order by rowint
/
2
David Aldridge

Abfrage zum Finden der Datumsdifferenz zwischen zwei Zeilen einer einzelnen Spalte 

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

Ich würde nur eine kleine Funktion dafür machen. Wenn Sie die beiden Werte eingeben, müssen Sie den Unterschied kennen und den kleineren vom größeren Wert abziehen. So etwas wie:

CREATE FUNCTION [dbo].[NumDifference] 
    (   @p1 FLOAT,
        @p2 FLOAT )
RETURNS FLOAT
AS
BEGIN
    DECLARE @Diff FLOAT
    IF @p1 > @p2 SET @Diff = @p1 - @p2 ELSE SET @Diff = @p2 - @p1
    RETURN @Diff
END

In einer Abfrage, um den Unterschied zwischen Spalte a und b zu ermitteln:

SELECT a, b, dbo.NumDifference(a, b) FROM YourTable
0
Nosegear
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
mns