3

私はこのようなテーブルを持っています

childid      parentid
------------------------
1       0
2       1
3       2
4       2
5       3
6       4
7       0
8       7
9       8
10      1

子IDを5とすると、親IDは1(出力)になります。

子IDを9とすると、親IDは7になります。(出力)

つまり、ルートの親IDは0であり、クエリはそこで停止する必要があります。

そのようなクエリを解決する方法は?

助けてください。

4

4 に答える 4

5

child_idの名前をnodeに、parent_idの名前をchild_ofに変更する必要があると思います。列の命名は少し紛らわしいです

create table stack_overflow
(
node int, child_of int
);


insert into stack_overflow(node, child_of) values
(1,0),
(2,1),
(3,2),
(4,2),
(5,3),
(6,4),
(7,0),
(8,7),
(9,8),
(10,1);

これは、CTE対応のRDBMSで機能します

with find_parent(parent, child_of, recentness) as
(
    select node, child_of, 0 
    from stack_overflow
    where node = 9
    union all
    select i.node, i.child_of, fp.recentness + 1
    from stack_overflow i
    join find_parent fp on i.node = fp.child_of
)
select top 1 parent from find_parent 
order by recentness desc

出力:

parent
7

[編集:より柔軟で将来性のある]

with find_parent(node_group, parent, child_of, recentness) as
(
    select node, node, child_of, 0
    from stack_overflow
    where node in (5,9)
    union all
    select fp.node_group, i.node, i.child_of, fp.recentness + 1
    from stack_overflow i
    join find_parent fp on i.node = fp.child_of
)
select q.node_group as to_find, parent as found 
from find_parent q 
join
(
    select node_group, max(recentness) as answer
    from find_parent
    group by node_group 
) as ans on q.node_group = ans.node_group and q.recentness = ans.answer 
order by to_find    

出力:

to_find     found
5           1
9           7

Postgresを使用している場合、上記のコードは次のように短縮できます。

with recursive find_parent(node_group, parent, child_of, recentness) as
(
    select node, node, child_of, 0
    from stack_overflow
    where node in (5,9)
    union all
    select fp.node_group, i.node, i.child_of, fp.recentness + 1
    from stack_overflow i
    join find_parent fp on i.node = fp.child_of
)
select distinct on (node_group) node_group as to_find, parent as found 
from find_parent 
order by to_find, recentness desc

岩の違い!:-)

于 2009-07-10T05:48:54.400 に答える
4

必要なのがルートParentIDだけの場合は、次の再帰関数を使用できます。

CREATE FUNCTION test_func
(
    @ParentID int
)
RETURNS int
AS
BEGIN
    DECLARE @result int;
    DECLARE @childID int;

    SET @childID = (SELECT ChildID FROM YourTable WHERE ParentID = @ParentID)

    IF (@childID = 0)
        SET @result = @ParentID
    ELSE
        SET @result = dbo.test_func(@childID)

    RETURN @result    
END
GO

次に、メインクエリで:

SELECT dbo.test_func(5)

提供されたデータに基づいて、5を渡すと1が返され、9は7が返されます。そのチェーンの上位にあるすべてのParentIDが必要な場合は、おそらくCTEを使用する必要があります。

于 2009-07-09T16:35:47.437 に答える
0

再帰クエリが必要だと思います。共通テーブル式を使用する必要があります。使用している例と非常によく似た例のリンクを示します。

これが解決策だと思います。それは数ヶ月前に私を助けました。

于 2009-07-09T16:33:11.920 に答える
0

特定の子IDと一致する親IDを取得する簡単な例は次のとおりです。

select parentid 
from MyTable 
where childid = 5

ただし、上記のデータの場合、これはレコードを返しません。

于 2009-07-09T16:34:17.173 に答える