SQL история чистых повторных промежуточных значений - PullRequest
1 голос
/ 06 апреля 2020

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

product | price | date
------------------------
1       | 1     | 1
1       | 1     | 2
1       | 1     | 3
1       | 1     | 4
2       | 77    | 5
1       | 1     | 6
1       | 2     | 7
1       | 2     | 8
1       | 1     | 9
1       | 1     | 10
1       | 1     | 11
1       | 1     | 12
1       | 3     | 13

К этому:

product | price | date
------------------------
1       | 1     | 1
2       | 77    | 5
1       | 2     | 7
1       | 1     | 9
1       | 3     | 13

Также предположим, что в этом случае столбец id совпадает с date.

SELECT DISTINCT ON (product, price) не будет работать, поскольку он игнорирует либо product 1 изменение в день 9 или 1, проблема в том, что я хочу сгруппировать по product, price, но только через определенные промежутки времени в соответствии с соответствующими изменениями по date.

Даже если можно заказать product, трудно игнорировать date и price порядок изменения.

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

У кого-нибудь есть предложения?

Ответы [ 3 ]

2 голосов
/ 06 апреля 2020

Это проблема пробелов и островков, когда вы хотите сгруппировать смежные строки одного и того же продукта с одинаковой ценой.

Вот один из подходов, использующий разницу между номерами строк для определения групп

select product, price, min(date) date
from (
    select 
        t.*,
        row_number() over(partition by product order by date) rn1,
        row_number() over(partition by product, price order by date) rn2
    from mytable t
) t
group by product, price, rn1 - rn2
order by min(date)

Демонстрация на DB Fiddle :

product | price | date
------: | ----: | ---:
      1 |     1 |    1
      2 |    77 |    5
      1 |     2 |    7
      1 |     1 |    9
      1 |     3 |   13
0 голосов
/ 06 апреля 2020

Похоже, вам нужен первый ряд при изменении цены. Если это так, я рекомендую lag():

select t.product, t.product, t.price
from (select t.*,
             lag(price) over (partition by product order by date) as prev_price
      from t
     ) t
where prev_price is null or prev_price <> price;

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

0 голосов
/ 06 апреля 2020

Удалите дублирующиеся строки, оставив их включенными (используйте min () или max () для сохранения самой старой / самой новой строки)

вы можете отфильтровать столбцы, которые должны определять дубликаты, сгруппировав

DELETE FROM MyTable WHERE RowId NOT IN (SELECT MIN(RowId) FROM MyTable GROUP BY Col1, Col2, Col3);
...