这是我的表格(emp_details)内容。 emp_id是"主键"和emp_man_id是"外键"引用emp_detais(emp_id)
自我参考表:
emp_id emp_name emp_place emp_man_name emp_man_id
1 arun klm arun
2 nivin thr arun 1
3 vinay ekm arun 1
4 ajo plk nivin 2
5 alan knr nivin 2
6 ravi tvm vinay 3
7 vipin mlp vinay 3
8 ani ksd ajo 4
9 vino pta ajo 4
11 sarat wyd alan 5
10 siva alp alan 5
如果我将值10作为员工ID传递,我需要为此表编写函数;
我需要输出
emp_id emp_man_id
10 5
5 2
2 1
这是我的功能:
CREATE OR REPLACE FUNCTION emp_e1(IN id integer)
RETURNS TABLE(em_id integer, emp_mid integer)
AS
$BODY$
begin
return query
with recursive d as (
select emp_id, emp_man_id, 0 as level
from emp_details
where emp_id = id
UNION ALL
select c.emp_id, c.emp_man_id, level+1
from d
inner join emp_details c on c.emp_man_id = d.emp_id
)
SELECT *
FROM d;
end;
$BODY$
LANGUAGE plpgsql;
答案 0 :(得分:3)
(编辑:回答是在编辑问题并添加postgresql
标记之前,在第一个问题的评论中SQL Server
已被提及(我不确定)也许我没有注意到,我错了),这就是为什么答案首先提供给MS SQL Server
但是在编辑问题后立即添加查询的postgresql
形式并向其添加postgresql标签。)
(对于MS SQL Server)
使用recursive cte
:
CREATE FUNCTION dbo.fn(@empId int)
RETURNS @t table (empid int, manid int)
as
begin
with cte (empid, manid) as
(
select emp_id,man_id
from emp where emp_id=@empId
union all
select e.emp_id, e.man_id
from emp e
join cte on e.emp_id=cte.manid
)
insert into @t
select * from cte;
return
end
(对于Postgresql)
PostgreSQL
只需在recursive
之前添加cte
关键字,然后将函数格式更改为Posgres格式。
with recursive cte (empid, manid) as
(
select emp_id,man_id
from emp where emp_id=10
union all
select e.emp_id, e.man_id
from emp e
join cte on e.emp_id=cte.manid
)
select * from cte
答案 1 :(得分:0)
使用递归CTE:
DECLARE @t TABLE
(
emp_id INT ,
emp_man_id INT
)
INSERT INTO @t
VALUES ( 1, NULL ),
( 2, 1 ),
( 3, 1 ),
( 4, 2 ),
( 5, 2 ),
( 6, 3 ),
( 7, 3 ),
( 8, 4 ),
( 9, 4 ),
( 11, 5 ),
( 10, 5 );
WITH cte
AS ( SELECT emp_id ,
emp_man_id
FROM @t
WHERE emp_id = 10
UNION ALL
SELECT t.emp_id ,
t.emp_man_id
FROM @t t
JOIN cte c ON t.emp_id = c.emp_man_id
WHERE t.emp_man_id IS NOT NULL
)
SELECT *
FROM cte
输出:
emp_id emp_man_id
10 5
5 2
2 1
包装功能:
CREATE FUNCTION dbo.Test ( @id INT )
RETURNS @t TABLE
(
emp_id INT ,
emp_man_id INT
)
AS
BEGIN
WITH cte
AS ( SELECT emp_id ,
emp_man_id
FROM TableName
WHERE emp_id = @id
UNION ALL
SELECT t.emp_id ,
t.emp_man_id
FROM TableName t
JOIN cte c ON t.emp_id = c.emp_man_id
WHERE t.emp_man_id IS NOT NULL
)
INSERT INTO @t
( emp_id, emp_man_id )
SELECT emp_id ,
emp_man_id
FROM cte
RETURN
END
答案 2 :(得分:0)
如果您需要经理的数据,我建议您使用此解决方案(在 SQL Server 中):
..\..\..\
)CREATE FUNCTION dbo.AllParents ( @emp_id int )
RETURNS varchar(max)
AS
BEGIN
Declare @result varchar(max), @emp_man_id int
Set @emp_man_id = (Select emp_man_id from temptable where emp_id = @emp_id)
--if you need also a function for finding children it will be same:
--Set @emp_man_id = (Select emp_id from temptable where emp_man_id = @emp_id)
if (@emp_man_id is Null)
set @result = ''
else
set @result = dbo.AllParents(@emp_man_id) + '\' + cast(@emp_man_id as varchar(max)) + '#'
return @result
END
GO
10
的示例):select * from temptable
where dbo.AllParents(10) like '%\' + cast(emp_id as varchar(max)) + '#%'
但上面的查询结果并不是你所展示的,但我认为是你想要的 - 这是所有经理人的最高级别的所有数据 - 。
如果您还希望获得emp_id = 10
的数据,可以将其添加到以下位置:
or emp_id = 10
如果您还添加了一个子功能,请将其添加到这样的
or dbo.AllChildren(10) like '%\' + cast(emp_id as varchar(max)) + '#%'
注意:对于排序管理员,您还可以使用order by
下面的
order by len(dbo.AllParents(emp_id))
注意:如果您还需要显示路径,请将该功能用作以下字段:
select *, replace(dbo.AllParents(emp_id), '#', '') from temptable