Как order_by ведет себя в sql, когда столбец order_by имеет повторяющиеся значения? - PullRequest
0 голосов
/ 19 июня 2019

Я использую запрос для заполнения нулевых значений, используя функцию 'first_value' из sql Весь запрос с примером выглядит следующим образом:

WITH example (date,close) AS 
(VALUES 
    ('12:00:00',3),
    ('12:00:01',4),
    ('12:00:01',5),
    ('12:00:03',NULL),
    ('12:00:04',NULL), 
    ('12:00:05',3)
)
SELECT * INTO temporary table market_summary FROM example;

select 
    date, 
    cccc, 
    first_value(cccc) over (partition by grp_close) as corrected_close
from (
      select date, close as cccc,
             sum(case when close is not null then 1 end) over (order by date) as grp_close
      from   market_summary
) t

Результат:


    date      cccc   corrected_close
1   12:00:00    3       3
2   12:00:01    4       4
3   12:00:01    5       4
4   12:00:03    NULL    4
5   12:00:04    NULL    4
6   12:00:05    3       3

Здесь, в этом примере, «date» используется в качестве столбца order_by в запросе, но имеет дубликат «12: 00: 01». Нулевые значения заполняются '4', что в идеале не правильно, так как я хочу, чтобы нулевые значения были заполнены предыдущими ненулевыми значениями, которые в этом случае '5', а не '4', так что результат должен быть таким, как показано ниже :


    date       cccc   corrected_close
1   12:00:00    3       3
2   12:00:01    4       4
3   12:00:01    5       5
4   12:00:03    NULL    5
5   12:00:04    NULL    5
6   12:00:05    3       3

Как мне изменить запрос, чтобы он соответствовал моим требованиям?

Ответы [ 2 ]

0 голосов
/ 19 июня 2019

То, что вы хотите, это lag( . . . ignore nulls). Но Postgres не поддерживает это.

Вот один из обходных путей:

select e.*, coalesce(close, max(close) over (partition by grp))
from (select e.*, count(close) over (order by date) as grp
      from example e
     ) e;

Вы даже можете сделать это без подзапроса:

select e.*,
       coalesce(close,
                (array_remove(array_agg(close) over (order by date), null))[array_upper(array_remove(array_agg(close) over (order by date), null), 1)]
               )

from example e;
0 голосов
/ 19 июня 2019

Вам следует изменить оконную функцию, чтобы получить правильное значение:

last_value(cccc) IGNORE NULLS OVER (PARTITION BY grp_close ORDER BY date)

Это способ, определенный стандартом SQL, но многие базы данных не реализуют стандарт в этом отношении. Поскольку вы пометили множество баз данных, сложно дать общий ответ, который подходит для всех из них.

...