Oracle 分析函数 - 使用 FIRST_VALUE 删除不需要的行
基于这两个问题,我相信 Oracle 函数 FIRST_VALUE 是我需要使用的: SQL - 如何选择具有具有最大值的列
Oracle:获取最大日期的记录
我有 3代表与组织相关的人员的表。每个组织可能有一个父组织,其中 ORG.PARENT 是 ORG.ID 的外键(因此该表引用其自身)。一个人可能与多个群体相关联。
PERSON
ID NAME
----------
1 Bob
ORG
ID NAME PARENT
------------------------
1 A (null)
2 A-1 1
3 A-2 1
4 A-3 1
5 A-1-a 2
6 A-1-b 2
7 A-2-a 3
8 A-2-b 3
PERSON_TO_ORG
PERSON_ID ORG_ID
-----------------
1 1
1 3
我想列出与某人关联的组,因此我使用了以下查询:
SELECT NAME, ID, sys_connect_by_path(NAME, '/') AS path
FROM org
START WITH ID IN
(SELECT org_id FROM person_to_org WHERE person_id=1)
connect by prior org.ID = org.parent;
...这给了我:
NAME ID PATH
------------------
A-2 3 /A-2
A-2-a 8 /A-2/A-2-a
A-2-b 9 /A-2/A-2-b
A 1 /A
A-1 2 /A/A-1
A-1-a 5 /A/A-1/A-1-a
A-1-b 6 /A/A-1/A-1-b
A-2 3 /A/A-2
A-2-a 8 /A/A-2/A-2-a
A-2-b 9 /A/A-2/A-2-b
A-3 4 /A/A-3
注意如何A-2 出现了两次,这是理所应当的。然而,我不希望一个团体出现两次。我希望一个组仅出现在树中的最低级别,即其最高级别值。以下是我尝试使用 FIRST_VALUE 的方法,但没有成功 - 我仍然让 A-2 (和其他)出现两次:
SELECT id, name, path, first_value(lev) OVER
(
PARTITION BY ID,NAME, path ORDER BY lev DESC
) AS max_lev FROM
(SELECT NAME, ID, sys_connect_by_path(NAME, '/') AS path, LEVEL as lev
FROM org START WITH ID IN
(SELECT org_id FROM person_to_org WHERE person_id=1)
connect by prior org.ID = org.parent);
这看起来与 Pro Oracle SQL 中的 FIRST_VALUE 示例类似,但我似乎无论如何都无法使其工作我调整参数。
如何仅返回给定组具有最高级别值的行(即树中最下面的行)?
I believe the Oracle function FIRST_VALUE is what I need to be using based on these two questions:
SQL - How to select a row having a column with max value
Oracle: Taking the record with the max date
I have 3 tables that represent people associated with organizations. Each organization may have a parent org, where ORG.PARENT is a foreign key to ORG.ID (so the table refers to itself). A person may be associated with more than one group.
PERSON
ID NAME
----------
1 Bob
ORG
ID NAME PARENT
------------------------
1 A (null)
2 A-1 1
3 A-2 1
4 A-3 1
5 A-1-a 2
6 A-1-b 2
7 A-2-a 3
8 A-2-b 3
PERSON_TO_ORG
PERSON_ID ORG_ID
-----------------
1 1
1 3
I want to list the groups a person is associated with so I used this query:
SELECT NAME, ID, sys_connect_by_path(NAME, '/') AS path
FROM org
START WITH ID IN
(SELECT org_id FROM person_to_org WHERE person_id=1)
connect by prior org.ID = org.parent;
...which gives me:
NAME ID PATH
------------------
A-2 3 /A-2
A-2-a 8 /A-2/A-2-a
A-2-b 9 /A-2/A-2-b
A 1 /A
A-1 2 /A/A-1
A-1-a 5 /A/A-1/A-1-a
A-1-b 6 /A/A-1/A-1-b
A-2 3 /A/A-2
A-2-a 8 /A/A-2/A-2-a
A-2-b 9 /A/A-2/A-2-b
A-3 4 /A/A-3
Notice how A-2 appears twice, as it should. I don't want a group to appear twice, however. I want a group to only appear at its lowest level in the tree, i.e. at its highest level value. Here is how I've tried using FIRST_VALUE with no luck - I still get A-2 (and others) appearing twice:
SELECT id, name, path, first_value(lev) OVER
(
PARTITION BY ID,NAME, path ORDER BY lev DESC
) AS max_lev FROM
(SELECT NAME, ID, sys_connect_by_path(NAME, '/') AS path, LEVEL as lev
FROM org START WITH ID IN
(SELECT org_id FROM person_to_org WHERE person_id=1)
connect by prior org.ID = org.parent);
This seems similar to the FIRST_VALUE example in Pro Oracle SQL but I can't seem to make it work no matter how I tweak the parameters.
How can I return only the rows where a given group has its highest level value (i.e. farthest down in the tree)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如您提到的其中一个线程中所说,分析并不是最有效的方法:您需要聚合以过滤掉重复项。
问候,
抢。
PS:以下是有关 LAST 聚合函数的更多信息: http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions071.htm#sthref1495
As also said in one of the threads you refer to, analytics are not the most efficient way to go here: you need to aggregate to filter out the duplicates.
Regards,
Rob.
PS: Here is some more information about the LAST aggregate function: http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions071.htm#sthref1495
这个怎么样(未经测试)
What about this (untested)
您应该仅对 OVER (PARTITION BY ID,NAME ORDER BY lev DESC) 进行分区
不是
ID、NAME、路径
编辑:
也许您想要
first_value(path)
,而不是first_value(lev)
You should partition only
OVER (PARTITION BY ID,NAME ORDER BY lev DESC)
not
ID,NAME, path
Edit:
And probably you want
first_value(path)
, notfirst_value(lev)