#sql #postgresql #sequence #greatest-n-per-group
#sql #postgresql #последовательность #наибольшее число на группу
Вопрос:
У меня есть таблица sample_1
в базе данных Postgres 10.7 с некоторыми данными продольных исследований и возрастающим sequence
числом для key
. Мне нужны INSERT
данные из промежуточной таблицы ( sample_2
), поддерживающие sequence
столбец соответствующим образом.
sequence
числа основаны на 0. Я предполагаю, что мне нужен запрос для поиска наибольшего sequence
числа на key
в sample_1
и добавления его к последующему порядковому номеру каждой новой строки. На этом этапе я в основном борюсь с арифметикой порядкового номера. Пробовал это:
INSERT INTO sample_1 (KEY, SEQUENCE, DATA)
SELECT KEY, sample_2.SEQUENCE max(sample_1.SEQUENCE), DATA
FROM sample_2;
Однако я получаю ошибки, в которых говорится, что я не могу использовать ‘sample_1.SEQUENCE’ в строке 2, потому что это таблица, вставляемая в to. Я не могу понять, как выполнить арифметику с моей последовательностью вставки!
Пример данных:
sample_1
| KEY | SEQUENCE | DATA |
------------- ---------- ------
| YMH_0001_XX | 0 | a |
| YMH_0001_XX | 1 | b |
| YMH_0002_YY | 0 | c |
sample_2
| KEY | SEQUENCE | DATA |
------------- ---------- ------
| YMH_0001_XX | 1 | d |
| YMH_0002_YY | 1 | e |
| YMH_0002_YY | 2 | f |
Я хочу продолжить возрастание sequence
чисел на key
для вставленных строк.
Чтобы было понятно, результирующая таблица в этом примере будет состоять из 3 столбцов и 6 строк как таковых:
sample_1
| KEY | SEQUENCE | DATA |
------------- ---------- ------
| YMH_0001_XX | 0 | a |
| YMH_0001_XX | 1 | b |
| YMH_0001_XX | 2 | d |
| YMH_0002_YY | 0 | c |
| YMH_0002_YY | 1 | e |
| YMH_0002_YY | 2 | f |
Комментарии:
1. Если вы добавляете
max(seq)
insample_1
ко всем строкам, не должно лиsequence
последних 2 строк в вашей результирующей таблице быть 2 и 3?2. @Crazy2crack — Я не уверен, что понимаю, почему? Единственной строкой в ‘1’ для YMH_0002 является sequence == 0, поэтому max (1.sequence) 2.sequence равно 1 и 2 соответственно? Базовая последовательность для каждого отдельного кода равна 0, а все последующие временные точки равны 1, 2 и т.д.
3. В идеале вы предоставляете свою версию Postgres и точные определения таблиц (
CREATE TABLE
инструкции, разъясняющие типы данных, ограничения, значения по умолчанию, …) А также раскрывает любые триггеры, последовательности и т.д., Которые могут быть задействованы.4. @ErwinBrandstetter — Спасибо. Я отредактирую свой пост. Поскольку это мой первый пост, он дал мне экскурсию по его созданию и особо упомянул, что номера версий следует избегать, если это специально не требуется.
5. Я взял на себя смелость уточнить описание. Пожалуйста, отредактируйте, если я что-то не так понял.
Ответ №1:
Это должно делать то, что вам нужно:
INSERT INTO sample_1 (key, sequence, data)
SELECT s2.key
, COALESCE(s1.seq_base, -1)
row_number() OVER (PARTITION BY s2.key ORDER BY s2.sequence)
, s2.data
FROM sample_2 s2
LEFT JOIN (
SELECT key, max(sequence) AS seq_base
FROM sample_1
GROUP BY 1
) s1 USING (key);
Примечания
-
Вам нужно использовать существующий максимум
sequence
наkey
вsample_1
. (Я назвал егоseq_base
.) Вычислите это в подзапросе и присоединитесь к нему. -
Добавьте
row_number()
к нему, как показано. Это сохраняет порядок входных строк, отбрасывая абсолютные числа. -
Нам нужно
LEFT
JOIN
, чтобы избежать потери строк с новыми ключами изsample_2
.
Аналогично, нам нужноCOALESCE
начать новую последовательность для новых ключей. По умолчанию используется значение -1, чтобы эффективно начинать последовательности с 0 после добавления номера строки на основе 1. -
Это небезопасно для одновременного выполнения, но я не думаю, что это ваш вариант использования.
Комментарии:
1. Большое спасибо, Эрвин! Я думаю, я могу видеть, как это будет работать — я посмотрю и посмотрю, как я иду.