sql - Oracle 分析函数 - 使用 FIRST_VALUE 删除不需要的行

标签 sql oracle oracle10g oracle-analytics

我相信基于以下两个问题,我需要使用 Oracle 函数 FIRST_VALUE :
SQL - How to select a row having a column with max value
Oracle: Taking the record with the max date

我有 3 个表,代表与组织相关的人员。每个组织可能有一个父组织,其中 ORG.PARENT 是 ORG.ID 的外键(因此该表指的是自身)。一个人可能与多个组相关联。



ID    NAME
----------
1     Bob

机构

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 示例,但无论我如何调整参数,我似乎都无法使其工作。

如何仅返回给定组具有最高级别值的行(即树中最远的行)?

最佳答案

正如您在引用的一个线程中所说,分析并不是最有效的方法:您需要聚合以过滤掉重复项。

SQL> SELECT id
  2       , max(name) keep (dense_rank last order by lev) name
  3       , max(path) keep (dense_rank last order by lev) path
  4    FROM ( SELECT NAME
  5                , ID
  6                , sys_connect_by_path(NAME, '/') AS path
  7                , LEVEL as lev
  8             FROM org
  9            START WITH ID IN (SELECT org_id FROM person_to_org WHERE person_id=1)
 10          connect by prior org.ID = org.parent
 11         )
 12   group by id
 13  /

        ID NAME  PATH
---------- ----- --------------------
         1 A     /A
         2 A-1   /A/A-1
         3 A-2   /A/A-2
         4 A-3   /A/A-3
         5 A-1-a /A/A-1/A-1-a
         6 A-1-b /A/A-1/A-1-b
         7 A-2-a /A/A-2/A-2-a
         8 A-2-b /A/A-2/A-2-b

8 rows selected.

问候,
抢。

PS:这里有一些关于 LAST 聚合函数的更多信息:http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions071.htm#sthref1495

关于sql - Oracle 分析函数 - 使用 FIRST_VALUE 删除不需要的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9046633/

相关文章:

sql - 在 Postgres 的单个索引中包含多个列

php - mySQL 语句 ORDER BY 多列

mysql - 如果行不存在则插入的过程或函数

java - oracle 数据库中的连接未关闭

sql - “列定义不明确”错误

Oracle 查询 - 优化

sql - 多选中的无效数字 - BI Publisher 10.1.3.4

sql - 我可以在 SQL Azure 中编写数据分类脚本吗

oracle - PL/SQL 中的转义下划线

oracle10g - 通配符查询扩展导致术语过多