简体   繁体   中英

SQL calculate intermediate days

suppose I have the following table and I am looking to extract the number of days between each positive and negative movement. In this way, then for each 'id' I have to calculate the intermediate days between each pair of dates and the proportion of the negative movement over the positive one, en SQL Teradata.

id   date  money
----------------
1    1-1   10
1    3-1   -5
1    9-1    8
1   10-1   -2
2    3-1   10
2    9-1  -10
2   15-1   20
2   19-1   -15


id  days_in prop
-----------------
1     2     0.5
1     1     0.25
2     6     1
2     4     0.75

You want something like this:

 select A.id, B.date - A.date as "days_in", (B.money - A.money)  / (b.date - A.date) 
 as "prop"
 from
 (
    select X.id, X.date, min(NextDate.date) as "MinNextDate", X.money
    from [yourTable] X, [yourtable] NextDate
    where
    NextDate.date > X.date
    and NextDate.id = X.id
 ) A,
[YourTable] B
where
   A.id = B.id
   and B.date = A.MinNextDate

I think that teradata returns a date difference as a number of days in integer format. If it is a dateTime, you may need to case the datetime values to dates before subtracting.

How about using a self join in a slightly different way, however it wil still produce extra rows since the join will be done with each row.. you can further restrict it based on your criteria

select a.id, (b.date-a.date) as days_in,
abs(b.money)/a.money as prop
from <table> a
inner join <table> b
on a.id=b.id
and a.date<>b.date
where (b.date-a.date)>0 and (abs(b.money)/a.money)>0
and (a.money>0 and b.money<=-1)

To get the previous positive value you can use last_value :

SELECT id
  ,datecol
  -- ratio between current negative and previous positive money
  ,Abs(Cast(money AS NUMBER)) /
   Last_Value(CASE WHEN money > 0 THEN money end IGNORE NULLS)
   Over (PARTITION BY id
         ORDER BY datecol)
  -- difference between current and previous date
  -- might need a cast to date or interval result if the datecol is a Timestamp
  ,datecol-
   Last_Value(CASE WHEN money > 0 THEN DATE_ end IGNORE NULLS)
   Over (PARTITION BY id
         ORDER BY datecol)
FROM vt AS t
-- return only rows with negative money
QUALIFY money < 0

Of course, this assumes there are always alternate rows with positive & negative values.

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