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

SQLFiddle demo

first_value также вариант:

select TGroup,
    first_value(Group_Desc) over (partition by tgroup order by subgroup) gd
  from t
Другие вопросы по тегам