Oracle - произвольно выбрать одну из нескольких строк на основе одного уникального ключа
Доброе утро! Я ищу трюк для поддержания уникального списка ключей, где может возникнуть отношение один ко многим.
проблема
Я работаю с ужасно ненормализованной базой данных на работе, и, к сожалению, о реорганизации не может быть и речи. У меня есть главная таблица 1NF, которая содержит ряд транзитивных и частичных зависимостей, подобных этой:
Cmpd_Key Group Subgroup Group_Desc
A1 | A | 1 | Same
A2 | A | 2 | Same
B1 | B | 1 | Same1
B2 | B | 2 | Same1
C1 | C | 1 | Diff1
C2 | C | 2 | Diff2 <---This field contains multiple values
Мне часто нужно вытащить уникальный список Group
Идентификаторы, но требования обычно требуют Group_Desc
поле также. К сожалению, из-за плохих ограничений на ввод данных в восходящем направлении, это поле описания может содержать несколько записей на Group
что вызывает дублирование как Group
поле должно быть уникальным в большинстве данных. Для моих целей мне все равно, какие Group_Desc
запись я тяну, пока я могу поддерживать отношения 1 Group
до 1 Group_Desc
,
Я придумала уродливое решение, которое я называю Inline View
всякий раз, когда мне нужно сослаться на Group_Desc
поле в большем запросе, но это убивает мою производительность:
SELECT Group, Group_Desc
FROM Table t
WHERE Subgroup = (SELECT MIN(Subgroup)
FROM Table
WHERE Group = t.Group) --Nasty Correlated Subquery
Вопрос
Есть ли у кого-нибудь удобный для исполнения трюк для повторного получения одной строки из нескольких значений в пределах одного и того же запроса? Я хотел бы иметь возможность отступить Group
и только первый Group_Desc
это появляется.
Я предполагаю что-то вроде этого:
SELECT Group, Group_Desc
FROM Table t
GROUP BY Group, Group_Desc
HAVING ROWNUM = [The lowest returned Rownum within the same Group]
Товарищ разработчик упомянул RANK
функционировать как возможное решение, но я не видел, как я мог бы использовать это, чтобы устранить значения.
Любая помощь, которую вы можете оказать, будет принята с благодарностью!
----------------РЕДАКТИРОВАТЬ----------------------
Поэтому после некоторого дополнительного анализа я смог указать на упущение в моем исходном коррелированном подзапросе, которое вызвало слишком длинный план выполнения. Добавив несколько дополнительных предикатов, оптимизатор смог создать лучший план, который изменил мое время выполнения примерно с 12 до 2 минут, что соответствует моим ожиданиям.
Я немного поэкспериментировал с решением Analytics, которое Ponder Stibbons предложил ниже. Его решение довольно элегантное, и я выбрал в качестве ответа на этот вопрос, однако я не смог использовать его в этом конкретном запросе, поскольку время выполнения было значительно медленнее, чем в моем исходном решении, главным образом из-за индекса, который я смог использовать в своем коррелированный подзапрос.
Я не сомневаюсь, что при справедливом сравнении решение Analytics будет работать наравне или лучше, чем решение Correlated SubQuery. Я ценю помощь каждого в этой проблеме!
1 ответ
Ты можешь использовать min
в аналитической версии здесь это быстро:
select
TGroup,
min(Group_Desc) over (partition by tgroup)
from t
first_value
также вариант:
select TGroup,
first_value(Group_Desc) over (partition by tgroup order by subgroup) gd
from t