Получить набор строк на основе определенной комбинации столбцов - PullRequest
0 голосов
/ 28 апреля 2020

Учитывая этот набор данных, каждый запас имеет ежегодный снимок стоимости.

+----+------+------+-------+-------+
| ID | Name | Year | Stock | Value |
+----+------+------+-------+-------+
|  1 | John | 2019 | ABC   |   123 |
|  1 | John | 2020 | ABC   |   123 |
|  1 | John | 2021 | ABC   |   123 |
|  1 | John | 2021 | XYZ   |   200 |
| 1  | John | 2022 | ABC   |   123 |
|  1 | John | 2022 | XYZ   |   200 |
|  1 | John | 2023 | ABC   |   630 |
|  1 | John | 2023 | XYZ   |   200 |
+----+------+------+-------+-------+

В 2019 году Джон держит только AB C со значением 123

В 2020 году Джон также держит только AB C со значением 123 (не имеет изменено)

В 2021 году Джон держит AB C, но также приобрел XYZ со значением 200

в 2022 году, Джон держит AB C и XYZ, оба значения не изменились.

В 2023 году Джон держит AB C и XYZ, при этом значение AB C увеличивается до 630, а значение XYZ остается на 200.

Я бы хотел возвращать строки, чтобы

  • В год, если ничего из портфеля Джона не изменилось С ПОСЛЕДНЕГО ГОДА, строки не возвращаются
  • Если что-то в портфеле Джона изменилось С ПОСЛЕДНЕГО ГОДА все его текущие авуары перечислены

Например,

+----+------+------+-------+-------+
| ID | Name | Year | Stock | Value |
+----+------+------+-------+-------+
|  1 | John | 2019 | ABC   |   123 |
|  1 | John | 2021 | ABC   |   123 |
|  1 | John | 2021 | XYZ   |   200 |
|  1 | John | 2023 | ABC   |   630 |
|  1 | John | 2023 | XYZ   |   200 |
+----+------+------+-------+-------+

Как мне это сделать, будь то через функции в PL / SQL или в чистом SQL?

1 Ответ

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

Если на пользователя не слишком много строк, то listagg() предоставляет удобное решение:

select ny.*
from (select name, year,
             listagg(stock || ':' || value, ',') within group (order by stock) as stocks,
             lag(listagg(stock || ':' || value, ',') within group (order by stock)) as prev_stocks,
             lag(year) over (partition by name order by year) as prev_year
      from t
      group by name, year
     ) ny
where prev_year is null or prev_year <> year - 1 or prev_stocks <> stocks;

Кроме того, вы можете проверить каждую строку отдельно и использовать функцию analyti c для проецирования информация по всем строкам в имени / году:

select t.*
from (select t.*,
             sum(case when prev_nsv_year = year then 0 else 1 end) over (partition by name, year) as num_diff,
             lag(cnt) over (partition by name order by year) as prev_cnt
      from (select t.*,
                   lag(year) over (partition by name, stock, value over order by year) as prev_nsv_year,
                   count(*) over (partition by name, year) as cnt
            from t
           ) t
     ) t
where cnt <> prev_cnt or prev_cnt is null or
      num_diff > 0;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...