Выбрать по массиву дат и на следующий день, если строки не существует? - PullRequest
0 голосов
/ 10 декабря 2018

Мне было интересно, можно ли одновременно выполнить условие IN и условие> (только если не найдено в IN) при сравнении дат из ряда дат?

Например,если 2018-01-01 не существует, он вытянет следующую доступную строку даты 2018-01-02, и это должно быть сделано для произвольного массива дат, который я предоставляю.(НЕ ДИАПАЗОН, так как это потянет даты, которые меня не интересуют.)

Пример:

create table trade (
    id serial primary key,
    year int,
    month int,
    "data" json
);

insert into trade ("year", "month", "data") VALUES (
  2018, 1, '{"2": {"low": 19, "high": 21, "open": 20, "close": 20, "volume": 1000}, "3": {"low": 19, "high": 21, "open": 20, "close": 20, "volume": 1000}}'::json
);

insert into trade ("year", "month", "data") VALUES (
  2018, 2, '{"1": {"low": 19, "high": 21, "open": 20, "close": 20, "volume": 1000}, "2": {"low": 19, "high": 21, "open": 20, "close": 20, "volume": 1000}}'::json

SELECT
 t.prices,
 make_date("year", "month", t.day::int) as date
FROM
trade
JOIN json_each(trade.data) t(day, prices) ON TRUE
WHERE
make_date("year", "month", t.day::int) IN ('2018-01-1', '2018-01-03')
);

Хотел бы, чтобы он возвращал цены 1950-01-03, 2018-01-03, И 2018-01-02 (поскольку 2018-01-01 не существует)

Я работаю над функцией, которая будет делать соотношение результатов 1/1, когда я предоставляю датыменя интересует, и если они не существуют, он вернет следующую доступную дату.

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Если предположить, что разрывы могут превышать один день, следующая функция представляется наиболее простым и эффективным решением:

create or replace function trade_on_dates(variadic date[])
returns table (prices json, date date) 
language plpgsql stable as $$
declare
    d date;
begin
    foreach d in array $1 loop
        return query select
            t.prices,
            make_date("year", "month", t.day::int) as date
        from trade
        join json_each(trade.data) t(day, prices) on true
        where make_date("year", "month", t.day::int) >= d
        order by 2
        limit 1;
    end loop;
end $$;

select *
from trade_on_dates('2018-01-01', '2018-01-03');

                              prices                              |    date    
------------------------------------------------------------------+------------
 {"low": 19, "high": 21, "open": 20, "close": 20, "volume": 1000} | 2018-01-02
 {"low": 19, "high": 21, "open": 20, "close": 20, "volume": 1000} | 2018-01-03
(2 rows)    
0 голосов
/ 10 декабря 2018

Вы можете использовать generate_series для проверки всех дат в заданном диапазоне.

SELECT
 t.prices,
 make_date("year", "month", t.day::int) as date
FROM
trade
JOIN json_each(trade.data) t(day, prices) ON TRUE
WHERE
("year"|| lpad( "month"::text,2,'0') || lpad(t.day,2,'0') )::DATE -- a simulation of 
                                                                 --your make_date function.

IN ( select 
           generate_series(DATE '2018-01-1',
                   DATE '2018-01-03',INTERVAL '1 DAY') ::DATE
);

Демо

Редактировать

И предположим, что я хотел назначить свидание в 1950-01-01, 2001-01-01 и 2002-01-04 и т. Д., И т. Д.

Выможет использовать несколько диапазонов в UNION ALL

..
IN ( select 
           generate_series(DATE '2018-01-1',
                   DATE '2018-01-03',INTERVAL '1 DAY') ::DATE
                   UNION ALL
     select 
           generate_series(DATE '1950-01-01',
                   DATE '1950-01-03',INTERVAL '1 DAY') ::DATE    
                   UNION ALL
     select 
           generate_series(DATE '2002-01-01',
                   DATE '2002-01-04',INTERVAL '1 DAY') ::DATE                  

)
..
..
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...