Oracle - 根据单个唯一键任意选择多行之一
Oracle - Arbitrarily pick one of multiple rows based on single unique key
早上好!我正在寻找一种技巧来维护可以发生一对多关系的唯一键列表。
问题
我在工作中使用了一个可怕的非规范化数据库,不幸的是重新设计是不可能的。我有一个 1NF master table,其中包含许多类似于此的传递和部分键依赖项:
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
ID 的唯一列表,但需求通常也需要 Group_Desc
字段。不幸的是,由于上游数据输入限制不佳,此描述字段可以包含每个 Group
的多个条目,这会导致重复,因为 Group
字段在大多数数据拉取中应该是唯一的。出于我的目的,我并不真正关心我提取了哪条 Group_Desc
记录,只要我可以保持 1 Group
到 1 Group_Desc
的关系即可。
我想出了一个丑陋的解决方案,每当我需要在更大的查询中引用 Group_Desc
字段时,我将其称为 Inline View
但这会降低我的性能:
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
function 是一种可能的解决方案,但我不知道如何使用它来消除值。
如果您能提供任何帮助,我们将不胜感激!
----------------编辑---------------------
所以在一些额外的分析之后,我能够指出我原来的相关子查询中的一个遗漏导致了一个过长的执行计划。通过添加一些额外的谓词,优化器能够创建一个更好的计划,将我的执行时间从大约 12 分钟更改为 2 分钟,这符合我的预期。
我对 Ponder Stibbons 在下面建议的 Analytics 解决方案做了很多实验。他的解决方案非常优雅,我选择作为这个问题的答案,但是,我无法在这个特定的查询中使用它作为
执行时间比我原来的解决方案慢得多,这主要是因为我能够在相关子查询中使用索引。
我毫不怀疑,在公平的比较中,Analytics 解决方案 运行 与 Correlated SubQuery 解决方案相当或更好。感谢大家对这个问题的帮助!
这里可以用解析版的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
早上好!我正在寻找一种技巧来维护可以发生一对多关系的唯一键列表。
问题
我在工作中使用了一个可怕的非规范化数据库,不幸的是重新设计是不可能的。我有一个 1NF master table,其中包含许多类似于此的传递和部分键依赖项:
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
ID 的唯一列表,但需求通常也需要 Group_Desc
字段。不幸的是,由于上游数据输入限制不佳,此描述字段可以包含每个 Group
的多个条目,这会导致重复,因为 Group
字段在大多数数据拉取中应该是唯一的。出于我的目的,我并不真正关心我提取了哪条 Group_Desc
记录,只要我可以保持 1 Group
到 1 Group_Desc
的关系即可。
我想出了一个丑陋的解决方案,每当我需要在更大的查询中引用 Group_Desc
字段时,我将其称为 Inline View
但这会降低我的性能:
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
function 是一种可能的解决方案,但我不知道如何使用它来消除值。
如果您能提供任何帮助,我们将不胜感激!
----------------编辑---------------------
所以在一些额外的分析之后,我能够指出我原来的相关子查询中的一个遗漏导致了一个过长的执行计划。通过添加一些额外的谓词,优化器能够创建一个更好的计划,将我的执行时间从大约 12 分钟更改为 2 分钟,这符合我的预期。
我对 Ponder Stibbons 在下面建议的 Analytics 解决方案做了很多实验。他的解决方案非常优雅,我选择作为这个问题的答案,但是,我无法在这个特定的查询中使用它作为 执行时间比我原来的解决方案慢得多,这主要是因为我能够在相关子查询中使用索引。
我毫不怀疑,在公平的比较中,Analytics 解决方案 运行 与 Correlated SubQuery 解决方案相当或更好。感谢大家对这个问题的帮助!
这里可以用解析版的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