Не так давно я говорил с моим другом, и мы обсудили немного другой, но довольно практический вопрос, о разбиении некоторого «стола» на группы, а затем нахождении argmax / argmin для каждой полученной группы.В частности, давайте предположим, что у нас есть таблица, в которой мы храним все версии некоторых сущностей (имеется в виду историю всех сущностей, а активная сущность является самой последней на ее вершине (истории)), так как мы можем наиболее эффективно выбирать толькоактивные записи из этой таблицы (точнее - разбить на группы по entity_id (не row_id) и найти argmax в каждой группе по столбцу версии).Поэтому, поскольку одной из моих первых мыслей о том, «как исследовать эту проблему», были ключевые слова «oracle sql argmax ИЛИ argmin», я публикую здесь свой комментарий.
Как говорит мне мой друг, они используют [PARTITION BY] [PARTITION-BY] ключевое слово для их средств, и как я могу видеть из fetch-the-row-which-has-the-max-value-for-a-column и receive-values-по отношению к максимальным и минимальным строкам в оракуле есть два варианта использования DENSE_RANK с "OVER (ORDER BY ...)" и затем привязать этот ранг к 1 (как описано здесь ив " fetch-the-row-which-has-the-max-value-for-a-column ") или используйте что-то вроде "max (version) over (partition by entity_id / not"row_id /) max_version ", а затем связать" version = max_version "в том месте, где его вызывают, как описано в" получение значений, относящихся к максимальным и минимальным строкам в оракуле"(" fetch-the-row-which-has-the-max-value-for-a-column"), и мой друг говорит, что они предпочитают именно второй подход, как я понял,Бекаиспользовать его может потребовать меньше вычислений для каждой группы, поскольку он находит только максимальное значение и не должен полностью сортировать каждую группу, с другой стороны, если будет более одной записи с таким же максимальным значением, этот запросвыберет не только одну произвольно выбранную строку с максимальным значением «столбца порядка» (в нашем случае), но все строки (из группы), которые имеют это максимальное значение (так, чтобы можно было возвращать Argmax - не только как одну строку, но итакже как набор строк, где это достигается).
Кроме того, как я понял, ключевое слово [KEEP] [KEEP] [LAST] / [FIRST] в [Oracle SQL] [oracle-sql-ref]предназначены для охвата варианта использования argmin / armax, в обоих вариантах - с группировкой [GROUP BY] [GROUP-BY] или [PARTITION BY] [PARTITION-BY], но так как они предполагают, что результат Argmax и Argmin может содержать несколькотоже строки (не только одна строка), вы не можете просто выбрать «эту строку», используя конструкцию [KEEP] ... [FIRST] / [KEEP] ... [LAST], вместо этого вы должны использовать некоторую [функцию агрегирования][Oracle-SQL-Совокупные-Фunctions], для «извлечения» некоторого значения из «этих строк» (Argmax-row), например (из [Oracle doc] [FIRST-Analytic-Example])
MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct)
OVER (PARTITION BY department_id) "Best"
где
KEEP (DENSE_RANK LAST ORDER BY commission_pct) OVER (PARTITION BY department_id)
предоставляет вам Argmax в виде набора строк (над отделом_id-group, с использованием в качестве критерия Commission_pct), а
MAX(salary)
предоставляет вам окончательную агрегацию по этим строкам Argmax (возможно, многочисленным).([Выбрать строку с максимальным значением] [Выбрать строку с максимальным значением] - обсуждение было отправной точкой для меня, чтобы я это понял).
Вот несколько справочных статей.
oracle-sql-ref Oracle-Sql-агрегатно-функции СОХРАНИТЬ ПЕРВЫЙ * 1 040 * ПЕРВЫЕ Аналитико-Example * * тысяча сорок один LAST Select-строка-с-Max-Value GROUP-BY PARTITION-BY ЗАКАЗАТЬ-BY-анализ
Функции SQL / query_partition_clause
DENSE_RANK MAX ROW_NUMBER
Вот несколько свободно цитируемых фрагментов о вышеупомянутых вещах.
с использованием [ROW_NUMBER] с [ORDER BY] [ORDER-BY-Analysis] и [PARTITION BY] [PARTITION-BY]
select row_id, entity_id, version, entity_value_1, entity_value_2
from (select row_id, entity_id, version, entity_value_1, entity_value_2,
row_number()
over (partition by entity_id order by version desc) as rank
from Entities) as r
where r.rank=1
с использованием [MAX] с [PARTITION BY] [PARTITION-BY]
select row_id, entity_id, version, max_version, entity_value_1, entity_value_2
from (select row_id, entity_id, version, entity_value_1, entity_value_2,
max(version) over (partition by entity_id) as max_version
from Entities) as r
where r.version=r.max_version
с использованием [KEEP] [KEEP] [LAST] / [FIRST]для подавления возможности появления нескольких строк с одинаковыми entity_id и версией в результате (среди Argmax-строк выбирается уникальная строка с максимальным row_id)
SELECT row_id, entity_id, version, max_version, entity_value_1, entity_value_2
FROM (SELECT
row_id, entity_id, version, entity_value_1, entity_value_2,
MAX(row_id)
KEEP (DENSE_RANK LAST ORDER BY version ASC)
OVER (PARTITION BY entity_id)
AS row_id_for_max_version
FROM Entities) as r
WHERE r.row_id=r.row_id_for_max_version