Как заставить запрос вернуть только первую строку из окна? - PullRequest
0 голосов
/ 26 июня 2019

У меня есть данные:

id | price | date
1  |    25 | 2019-01-01
2  |    35 | 2019-01-01
1  |    27 | 2019-02-01
2  |    37 | 2019-02-01

Можно ли написать такой запрос, который будет возвращать только первую строку из окна? что-то вроде LIMIT 1, но для окна OVER( date )?

Я ожидаю следующего результата:

id | price | date
1  |    25 | 2019-01-01
1  |    27 | 2019-02-01

Или игнорировать все окно, если первая строка окна имеет NULL:

id | price | date
1  |  NULL | 2019-01-01
2  |    35 | 2019-01-01
1  |    27 | 2019-02-01
2  |    37 | 2019-02-01

результат:

1  |    27 | 2019-02-01

Ответы [ 2 ]

1 голос
/ 26 июня 2019

Упорядочить строки по date и id и взять только первую строку для date. Затем удалите те, где цена равна NULL.

SELECT *
FROM (SELECT DISTINCT ON (date)
             id, price, date
      FROM mytable
      ORDER BY date, id
    ) AS q
WHERE price IS NOT NULL;

@ Лоренц, позвольте мне дать немного больше объяснений

select distinct on (<fldlist>) * from <table> order by <fldlist+>;

равно гораздо более сложному запросу:

select * from (
    select row_number() over (partition by <fldlist> order by <fldlist+>) as rn,*
    from <table>)
where rn = 1;

А здесь <fldlist> должна быть начальной частью (или равной) <fldlist+>

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

Как сказал Myon на IRC:

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

целевой запрос:

select * from (
  select
    *
    agg_function( my_field ) OVER( PARTITION BY other_field ) as agg_field
  from sometable
) x
WHERE agg_field <condition>

В моем случае у меня следующий запрос:

SELECT * FROM (
    SELECT *, 
      FIRST_VALUE( p.price ) over( PARTITION BY crate.app_period ORDER BY st.DEPTH ) AS first_price,
      ROW_NUMBER() over( PARTITION BY crate.app_period ORDER BY st.DEPTH ) AS row_number
    FROM st 
    LEFT JOIN price p ON <COND>
    LEFT JOIN currency_rate crate ON <COND>
) p
WHERE p.row_number = 1 AND p.first_price IS NOT null

Здесь я выбираю только первые строки из группы и где price IS NOT NULL

...