У меня есть следующая таблица ticks
Я хочу получить первое значение tick_lower_position
для tick_lower
, когда tick_lower <= lowest_tick
Таким образом, результирующая таблица должна выглядеть так
До сих пор я пытался применить решение, предоставленное @the-impaler, для других данных.
select y.*, first_value(tick_lower)
over(partition by g order by datetime) as tick_lower_position
from (
select x.*, sum(i) over(order by datetime) as g
from (
select t.*, case when lowest_tick <
lag(tick_lower) over(order by datetime)
then 1 else 0 end as i
from t
) x
) y
Но это решение не работает для текущего примера.
Как вы можете видеть в этом примере на db<>fidle я получил неправильное значение в 3-й строке. tick_lower_position
в 3-й строке все равно должно быть равно 204306
@TimBiegeleisen, потому что 204100
меньше 204120
Пожалуйста, правильно объясните свою цель.
What I want to get is to show the first value tick_lower_position for tick_lower when tick_lower <= lowest_tick
... пожалуйста, отредактируйте этот текст, чтобы отразить отставание, если это действительно ваша логика.
Простой ответ, но вы могли бы просто использовать MIN()
в качестве оконной функции вместе с выражением CASE
:
SELECT *, MIN(CASE WHEN tick_lower < lowest_tick THEN tick_lower END)
OVER (ORDER BY datetime) AS tick_lower_position
FROM yourTable
ORDER BY datetime;
Спасибо за ваш ответ! К сожалению, предложенное решение не дает желаемого результата. дб<>рабочий пример
Пожалуйста, отредактируйте свой вопрос и четко объясните ожидаемый результат.
Проблема (насколько я понял из расплывчатого описания и комментариев) не поддается естественному использованию чистого SQL. Похоже на случай процедурного решения:
Создайте эту функцию один раз:
CREATE OR REPLACE FUNCTION my_func()
RETURNS TABLE (datetime timestamp, lowest_tick int, tick_lower int, tick_lower_position int)
LANGUAGE plpgsql AS
$func$
DECLARE
r tbl; -- use table type as row variable
_tick_lower_position int;
BEGIN
FOR r IN
SELECT * FROM tbl t ORDER BY t.datetime
LOOP
IF r.lowest_tick > _tick_lower_position THEN
-- do nothing
ELSE
_tick_lower_position := CASE WHEN r.tick_lower <= r.lowest_tick THEN r.tick_lower END;
END IF;
RETURN QUERY
SELECT r.*, _tick_lower_position; -- output row
END LOOP;
END
$func$;
Затем позвоните:
SELECT * FROM my_func();
Я разрешаю tick_lower_position
по умолчанию NULL
, если указанное вами условие tick_lower <= lowest_tick
не выполняется.
Это невероятно! Большое вам спасибо за вашу помощь!
Запрос, который вы пробовали, почти готов, вам просто нужен еще один слой, получающий least()
предшествующее значение tick_lower_position и текущее значение tick_lower. Смотрите демо:
select z.datetime
, z.lowest_tick
, z.tick_lower
, least(lag(tlp) over(), tick_lower) tick_lower_position
from ( select y.*
, first_value(tick_lower) over(partition by g order by datetime) as tlp
from ( select x.*, sum(i) over(order by datetime) as g
from ( select ticks.*
, case when lowest_tick < lag(tick_lower) over(order by datetime)
then 1 else 0 end as i
from ticks
) x
) y
) z;
Спасибо за ваш ответ! Тем не менее, tick_lower_position для последней строки должно быть равно 204100, но в вашей демонстрации оно равно 204020.
Почему
204100
нижнее правое значение? Разве204020
не меньше204120
?