SQL вычисляет промежуточные дни

предположим, у меня есть следующая таблица, и я хочу извлечь количество дней между каждым положительным и отрицательным движением. Таким образом, затем для каждого «id» я должен рассчитать промежуточные дни между каждой парой дат и пропорцию отрицательного движения по положительному, 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

person lolo    schedule 07.01.2019    source источник
comment
Можете ли вы сделать самостоятельное соединение и проверить разницу. Не получить именно то, что вам нужно. Возможно, вам придется объяснить проблему / результат, необходимый лучше. Добавьте имя (таблица A и B) к данным, которые у вас есть в вашем вопросе.   -  person Acewin    schedule 07.01.2019
comment
Какой тип данных столбца вы используете для столбца даты? Выше это выглядит так, как будто это строка, но действительно ли это дата и время?   -  person Mike Wodarczyk    schedule 07.01.2019
comment
Да, это будет настоящее свидание.   -  person lolo    schedule 07.01.2019
comment
Что делать, если есть несколько последовательных строк с положительными или отрицательными значениями? Что делать, если есть две строки с одной и той же датой?   -  person dnoeth    schedule 07.01.2019


Ответы (3)


Вы хотите что-то вроде этого:

 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

Я думаю, что teradata возвращает разницу в дате в виде количества дней в целочисленном формате. Если это dateTime, вам может потребоваться преобразовать значения datetime в даты перед вычитанием.

person Mike Wodarczyk    schedule 07.01.2019
comment
В производной таблице отсутствует GROUP BY. И в зависимости от количества строк на идентификатор может потребоваться много ресурсов ЦП из-за неэквивалентного соединения. - person dnoeth; 08.01.2019

Как насчет того, чтобы использовать самосоединение немного по-другому, однако оно все равно будет создавать дополнительные строки, поскольку соединение будет выполняться с каждой строкой. Вы можете дополнительно ограничить его на основе ваших критериев.

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)
person Rhythm    schedule 07.01.2019

Чтобы получить предыдущее положительное значение, вы можете использовать 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

Конечно, это предполагает, что всегда есть чередующиеся строки с положительными и отрицательными значениями.

person dnoeth    schedule 07.01.2019