Отказ от ответственности: Показанная проблема гораздо более общая, чем я ожидал.Пример ниже взят из решения другого вопроса.Но теперь я взял этот образец для решения многих проблем больше - в основном, связанных с временными рядами (посмотрите на раздел «Связанные» в правой панели).
Поэтому я пытаюсь объяснить проблему в более общем видепервое:
Я использую PostgreSQL, но я уверен, что эта проблема существует и в других оконных функциях, поддерживающих СУБД (MS SQL Server, Oracle, ...).
Оконные функции могут использоваться для группировки определенных значений по общему атрибуту или значению.Например, вы можете сгруппировать строки по дате.Затем вы сможете рассчитать максимальное значение в пределах каждой отдельной даты или среднего значения или числа строк или чего-либо еще.
Это может быть достигнуто путем определения PARTITION
.Группировка по датам будет работать с PARTITION BY date_column
.Теперь вы хотите выполнить операцию, которая требует особого порядка в ваших группах (вычисление номеров строк или суммирование столбцов).Это можно сделать с помощью PARTITON BY date_column ORDER BY an_attribute_column
.
Теперь подумайте о более точном разрешении временных рядов.Что делать, если у вас нет дат, но отметок времени.Тогда вы больше не сможете группировать по столбцу времени.Но, тем не менее, может быть важно проанализировать данные в порядке их добавления (возможно, отметка времени - это время создания вашего набора данных).Затем вы понимаете, что некоторые последовательные строки имеют одинаковое значение, и вы хотите сгруппировать данные по этому общему значению.Но подсказка в том, что строки имеют разные временные метки.
Проблема в том, что вы не можете сделать PARTITION BY value_column
.Потому что PARTITION BY
вызывает порядок первым.Таким образом, ваш стол будет упорядочен value_column
перед группировкой и больше не упорядочен по временной метке.Это дает результаты, которые вы не ожидаете.
В более общем плане: Проблема заключается в том, чтобы обеспечить специальный порядок, даже если упорядоченный столбец не является частью созданного раздела .
Пример:
дБ <> скрипка
У меня есть следующая таблица:
ts val
100000 50
130100 30050
160100 60050
190200 100
220200 30100
250200 30100
300000 300
500000 100
550000 1000
600000 1000
650000 2000
700000 2000
720000 2000
750000 300
У меня была проблема с тем, что мне пришлось сгруппировать все связанные значения столбца val
.Но я хотел удержать заказ на ts
.Для этого я хотел добавить столбец с уникальным идентификатором для val
группы
Ожидаемый результат:
ts val group
100000 50 1
130100 30050 2
160100 60050 3
190200 100 4
220200 30100 5 \ same group
250200 30100 5 /
300000 300 6
500000 100 7
550000 1000 8 \ same group
600000 1000 8 /
650000 2000 9 \
700000 2000 9 | same group
720000 2000 9 /
750000 300 10
Первая попытка было использование оконной функции rank
, которая обычно выполняла бы эту работу:
SELECT
*,
rank() OVER (PARTITION BY val ORDER BY ts)
FROM
test
Но в этом случае это не работает, потому что предложение PARTITION BY
сначала упорядочивает таблицу по столбцам ее разделов (val
в данном случае), а затем по ORDER BY
столбцам.Таким образом, заказ на val, ts
вместо ожидаемого заказа на ts
.Таким образом, результат, конечно, не был ожидаемым.
ts val rank
100000 50 1
190200 100 1
500000 100 2
300000 300 1
750000 300 2
550000 1000 1
600000 1000 2
650000 2000 1
700000 2000 2
720000 2000 3
130100 30050 1
220200 30100 1
250200 30100 2
160100 60050 1
Вопрос: Как получить идентификаторы группы по порядку на ts
?
Редактировать: Я добавил собственное решение ниже, но мне очень неловко с ним.Это кажется слишком сложным. Мне было интересно, есть ли лучший способ для достижения этого результата.