简体   繁体   中英

SQL: Difference between rows

I am trying to find the difference between two numbers corresponding to the same ID, but with two different conditions. For example,

Column A Column B Column C
1234     3         True 
1234     5         False
5678     10        True
5678     15        False

So basically i want to find the difference in Column B when column A is the same but Column C is different.

If we can assume

  • 2 rows for a given value in ColumnA
  • expected result is only 1 row returned per unique colA value
  • columnC will never be null...
  • Column B will never match, and if they do, you don't want the record returned.

We can use a self join checking for matches on column A, no matches on column C and so that we don't get a row each for 1234 of 2 and -2.

SELECT Z.ColumnA, Z.B-Y.B
FROM TableName Z
INNER JOIN tableName Y
 on Z.ColumnA = Y.ColumnA
and Z.ColumnC <> Y.ColumnC
and Z.ColumnB > Y.ColumnB

you could also do this with a window function using lead and look ahead to the next record. but I don't know if your RDBMS supports window functions.

 select t1.ColumnA, t1.ColumnB-t2.ColumnB diff from
 tab t1, tab t2
 where t1.columnA = t2.columnA and t1.ColumnC='True' and t2.ColumnC='False'

If your table name is myTable , I believe you can join the table with itself and on Column A and then select a difference in Column B when Column C is not equal to itself. So something like this

SELECT X.ColumnB - Y.ColumnB as Diff
FROM myTable as X
inner join
     myTable as Y
on X.ColumnA=Y.ColumnA
WHERE X.ColumnC <> Y.ColumnC

You could use a self join

  select a.column_A, a,column_B, b.column_B, a.column_B . b.column_B
  from my_table a 
  inner join my_column b where a.column_a = b.column_a and a.column_c <> b_column_c

If you RDBMS supports window functions

;with cte as (
    Select *
          ,Change    = ColumnB-Lag(ColumnB,1) over (Partition By ColumnA Order By (Select null))
          ,TrueFalse = Lag(ColumnC,1) over (Partition By ColumnA Order By (Select null))
    From @YourTable
)
Select ColumnA
      ,Change
 From  cte
 Where Change<>0
   and TrueFalse<>ColumnC

Returns

ColumnA Change
1234    2
5678    5

This one subtracts the "true" rows from the "false" rows, while preserving all true rows.

SELECT true.columna, true.columnb, COALESCE(false.columnb, 0) - true.columnb AS difference
FROM
(SELECT *
 FROM t
 WHERE columnc = "true") true
LEFT JOIN
(SELECT *
 FROM t
 WHERE columnc = "false) false
ON true.columna = false.columna

The coalesce clause will account for cases in which there is no false row. Without it you will end up trying to subtract from NULL.

If you're using Oracle, take a look at User Defined aggregate functions . If you define a function called diff() , then you can use select column_A, diff(column_B) from my_table group by column_A , but remember that the implementation of diff needs special care as different ordering will generate different results.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM