我不确定获得我正在寻找的结果的最佳方法是什么。在一个oracle 10g数据库中,我正在尝试查询所有用户,并为每个拥有超级用户的行生成一个计算字段,如果他们的管理员类型是U.如果不是,我需要走到树上直到找到一个是。此查询可能需要递归多个级别。
对于像这样的Employee表:
Employee Table
+-------+----------+--------------+---------------+
| empno | empgroup | user | supervisor_no |
+-------+----------+--------------+---------------+
| 1 | E | Joe Schmo | 4 |
| 2 | E | Mark Marin | 3 |
| 3 | U | Reed Patter | 7 |
| 4 | E | Martin Price | 7 |
| 7 | U | Mary Wengert | |
+-------+----------+--------------+---------------+
我希望看到这样的结果,其中manager_no将是计算字段
Results
+-------+----------+--------------+---------------+------------+
| empno | empgroup | user | supervisor_no | Manager_No |
+-------+----------+--------------+---------------+------------+
| 1 | E | Joe Schmo | 4 | 7 |
| 2 | E | Mark Marin | 3 | 3 |
| 3 | U | Reed Patter | 7 | 7 |
| 4 | E | Martin Price | 7 | 7 |
| 7 | U | Mary Wengert | | |
+-------+----------+--------------+---------------+------------+
好的,所以我被问到我的尝试。我并不是说这是必须要这样做的,所以如果有人有更好的建议,我会全神贯注,但这就是我想要实现的目标。
我设想了两个部分。获取所有结果的主要查询
select em.empno, em.empgroup, em.user, em.supervisor, (my subquery) as manager_no
from employee em
查询:
select * from employee em
connect by prior supervisor_no = empno
start with empno = 1
[结果] [2] :
| EMPNO | EMPGROUP | USERNAME | SUPERVISOR_NO |
---------------------------------------------------
| 1 | E | Joe Schmo | 4 |
| 4 | E | Martin Price | 7 |
| 7 | U | Mary Wengert | (null) |
好的,我找到了一种方法来过滤可能有用的组,但不确定这是否是最有效的路线。
SELECT empno FROM (
SELECT empno FROM employee em
CONNECT BY PRIOR supervisor_no = empno
START WITH empno = 1
order by level) d
WHERE d.empgroup = 'U' and rownum =1
如果有帮助,我也创造了一个小提琴。 http://www.sqlfiddle.com/#!4/c8805/4
答案 0 :(得分:2)
嗯,你的问题对我来说是一个很大的挑战,但我并没有放弃,只使用sql和内置函数(不应该工作缓慢,并且需要相当可索引):
select distinct
empno,
empgroup,
username,
supervisor_no,
manager_no
from (
select
e.*,
decode(
instr(
sys_connect_by_path(empgroup, '/'),
'U/',
-1
),
0,
null,
substr(
sys_connect_by_path(empno, '/'),
instr(
sys_connect_by_path(empno, '/'),
'/',
1,
length(
substr(
sys_connect_by_path(empgroup, '/'),
1,
instr(
sys_connect_by_path(empgroup, '/'),
'U/',
-1
)
)
) - length(
replace(
substr(
sys_connect_by_path(empgroup, '/'),
1,
instr(
sys_connect_by_path(empgroup, '/'),
'U/',
-1
)
),
'/'
)
)
) + 1,
instr(
sys_connect_by_path(empno, '/'),
'/',
1,
length(
substr(
sys_connect_by_path(empgroup, '/'),
1,
instr(
sys_connect_by_path(empgroup, '/'),
'U/',
-1
)
)
) - length(
replace(
substr(
sys_connect_by_path(empgroup, '/'),
1,
instr(
sys_connect_by_path(empgroup, '/'),
'U/',
-1
)
),
'/'
)
) + 1
) - instr(
sys_connect_by_path(empno, '/'),
'/',
1,
length(
substr(
sys_connect_by_path(empgroup, '/'),
1,
instr(
sys_connect_by_path(empgroup, '/'),
'U/',
-1
)
)
) - length(
replace(
substr(
sys_connect_by_path(empgroup, '/'),
1,
instr(
sys_connect_by_path(empgroup, '/'),
'U/',
-1
)
),
'/'
)
)
) - 1
)
) manager_no
from employee e
connect by prior empno = supervisor_no
)
where manager_no is not null or supervisor_no is null
order by empno;
查询的SQL小提琴:http://www.sqlfiddle.com/#!4/c8805/27/0
<强>更新强> 当我早上起床时,我意识到一切都可以更轻松地完成,查询变得更具可读性,在这里:
select
empno,
empgroup,
username,
supervisor_no,
null manager_no
from
employee
where
supervisor_no is null
union all
select
empno,
empgroup,
username,
supervisor_no,
substr(ep, 2, instr(ep, '/', 2)-2) manager_no
from (
select
sys_connect_by_path(empgroup, '/') gp,
sys_connect_by_path(empno, '/') ep,
e.*
from employee e
connect by prior empno = supervisor_no
) e
where
substr(gp, 1, 3) = '/U/'
and (length(gp) - length(replace(gp, 'U/'))) = length('U/')
order by empno;
它有效!以及上面的查询。 SQL小提琴:http://www.sqlfiddle.com/#!4/c8805/54/0
享受!
答案 1 :(得分:0)
也许创建一个递归函数来获取用户的'U'类型的主管?
CREATE OR REPLACE FUNCTION GET_U_SUPERVISOR(employee_no INT)
RETURN INT IS
supervisor_empno INT;
supervisor_group VARCHAR(20);
BEGIN
SELECT empno, empgroup
INTO supervisor_empno, supervisor_group
FROM employee
WHERE employee.empno = (SELECT supervisor_no FROM employee WHERE empno = employee_no);
IF 'U' = supervisor_group
THEN
RETURN supervisor_empno;
ELSE
RETURN GET_U_SUPERVISOR(supervisor_empno);
END IF;
END GET_U_SUPERVISOR;
/
然后:
SELECT empno, empgroup, username, supervisor_no, GET_U_SUPERVISOR(empno)
FROM employee;
一个SQL小提琴回复你:http://www.sqlfiddle.com/#!4/c7540/1/0
但是,如果它是一张大桌子,我不能保证会有任何表现。它是递归的,并且将按行进行调用。答案 2 :(得分:-1)
我使用WITH递归,SQL Fiddle,
CREATE TABLE EMPLOYEE(NO INT, EMP_GROUP VARCHAR2(1), EUSER VARCHAR2(30), SUPERVISOR_NO INT);
INSERT INTO EMPLOYEE VALUES(1, 'E', 'JOE SCHMO', 4);
INSERT INTO EMPLOYEE VALUES(2, 'E', 'Mark Marin', 3);
INSERT INTO EMPLOYEE VALUES(3, 'U', 'Reed Patter', 7);
INSERT INTO EMPLOYEE VALUES(4, 'E', 'Martin Price ', 7);
INSERT INTO EMPLOYEE(NO, EMP_GROUP, EUSER) VALUES(7, 'U', 'Mary Wengert');
WITH A(EMPLOYEE, MANAGER) AS
(
SELECT NO AS EMPLOYEE, SUPERVISOR_NO AS MANAGER FROM EMPLOYEE
UNION ALL
SELECT A.EMPLOYEE, E.SUPERVISOR_NO AS MANAGER
FROM A, EMPLOYEE E
WHERE A.MANAGER = E.NO
AND E.SUPERVISOR_NO IS NOT NULL
)
SELECT * FROM A
ORDER BY 1