POSTGRESQL: перечислить с тем же номером при одинаковых критериях - PullRequest
0 голосов
/ 08 мая 2020

Что у меня есть

id | value
1 | foo
2 | foo
3 | bah
4 | bah
5 | bah
6 | jezz
7 | jezz
8 | jezz
9 | pas
10 | log

Что мне нужно: перечислить строки, как в следующем примере

id | value | enumeration
1 | foo | 1
2 | foo | 1
3 | bah | 2
4 | bah | 2
5 | bah | 2
6 | jezz | 3
7 | jezz | 3
8 | jezz | 3
9 | pas | 4
10 | log | 5

Я пробовал row_number с избыточным разделом. Но это приводит к другому виду перечисления.

Спасибо за любую помощь

1 Ответ

2 голосов
/ 08 мая 2020

Вы можете использовать rank() или dense_rank() для этого случая:

Щелкните: demo: db <> fiddle

SELECT
    *,
    dense_rank() OVER (ORDER BY value)
FROM
    mytable

rank() генерирует порядковый номер для каждого элемента группы, но он создает пробелы (если бы в первой группе было 3 элемента, вторая группа, начинающаяся в строке 4, получила бы номер 4). dense_rank() позволяет избежать этих пробелов.

Обратите внимание, что это упорядочивает таблицу по столбцу value в алфавитном порядке. Итак, результат будет: blah == 1, foo == 2, jezz == 3, log == 4, pas == 5.


Если вы хотите сохранить свой заказ, вам нужен дополнительный критерий заказа . В вашем случае вы можете использовать столбец id для создания такого столбца, если другой недоступен:

Щелкните: demo: db <> fiddle

Сначала используйте first_value(), чтобы найти наименьшее id для каждой группы значений:

SELECT
    *,
    first_value(id) OVER (PARTITION BY value ORDER BY id)
FROM
    mytable

Это первое значение (foo == 1, blah == 3, ...) можно использовать для сохранения исходного порядка, когда вычисление dense_rank():

SELECT
    id,
    value,
    dense_rank() OVER (ORDER BY first_value)
FROM (
    SELECT
       *,
       first_value(id) OVER (PARTITION BY value ORDER BY id)
    FROM
       mytable
) s
...