Вставить в таблицу на основе значения соответствующей строки - PullRequest
0 голосов
/ 14 июля 2020

Как мне выполнить запрос на вставку, который использует столбец matcher, чтобы выяснить, к какому groupID принадлежит строка, и использовать это значение groupID при вставке. А если совпадений нет - создайте новую группу. Последний случай легко выполнить с помощью отдельного запроса, но мне интересно, можно ли их объединить.

Таблица исходных групп:

| groupID |  val  | matcher |
| :-----: | :---: | :-----: |
|   g1    |  v1   |    a    |
|   g1    |  v2   |    a    |
|   g2    |  v3   |    b    |
|   g2    |  v4   |    b    |

Новые значения

|  val  | matcher |
| :---: | :-----: |
|  v5   |    a    |
|  v6   |    a    |
|  v7   |    b    |
|  v8   |    c    |
|  v9   |    c    |

После запроса:

| groupID |  val  | matcher |
| :-----: | :---: | :-----: |
|   g1    |  v1   |    a    |
|   g1    |  v2   |    a    |
|   g2    |  v3   |    b    |
|   g2    |  v4   |    b    |
|   g1    |  v5   |    a    |
|   g1    |  v6   |    a    |
|   g2    |  v7   |    b    |
|   g3    |  v8   |    c    |
|   g3    |  v9   |    c    |

Пояснение:

  1. v5 и v6 имеют то же matcher, что и значения в groupID из g1, поэтому они были вставлены с g1 id
  2. v7 имели тот же matcher, что и группа g2, следовательно, аналогичным образом он был вставлен в эту группу
  3. v8 имел совпадений нет, поэтому была сгенерирована новая группа g3 (сгенерированная groupID не обязательно должна быть последовательной)
  4. v9 не имела совпадений в исходной таблице, но поскольку она имеет тот же сопоставитель как v8, который ранее создал группу, он вставляется в группу v8

Псевдокод

for value in newvalues:
  existing = mygroups.findWhere(groupvalue.matcher == value.matcher)
  if existing != null:
    mygroups.insert({groupID: existing.groupID, val: value.val, matcher: value.matcher})
  else: 
    mygroups.insert({groupID: generated(), val: value.val, matcher: value.matcher})

1 Ответ

1 голос
/ 14 июля 2020

Думаю, я понимаю. Вам просто нужно либо сопоставить группы, либо создать новые. Я не собираюсь быть привязанным к вашим соглашениям об именах - это немного сложно. Фактически, я бы просто сделал группы числами, а не строками.

Но это генерирует новые группы:

with newvalues as (
      select 'v5' as val, 'a' as matcher union all
      select 'v6' as val, 'a' as matcher union all
      select 'v7' as val, 'b' as matcher union all
      select 'v8' as val, 'c' as matcher union all
      select 'v9' as val, 'c' as matcher
     )
select nv.*,
       coalesce(i.groupid,
                'new_group' || dense_rank() over (partition by i.groupid order by nv.matcher)::text
               ) as groupid
from newvalues nv left join
     initial i
     on nv.matcher = i.matcher;

И это вставляет значения:

with newvalues as (
      select 'v5' as val, 'a' as matcher union all
      select 'v6' as val, 'a' as matcher union all
      select 'v7' as val, 'b' as matcher union all
      select 'v8' as val, 'c' as matcher union all
      select 'v9' as val, 'c' as matcher
     )
insert into initial (groupid, val, matcher)
    select coalesce(i.groupid,
                    'new_group' || dense_rank() over (partition by i.groupid order by nv.matcher)::text
                   ) as groupid,
           nv.val, nv.matcher
    from newvalues nv left join
         initial i
         on nv.matcher = i.matcher;

Здесь - скрипт db <>.

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