我有下一张桌子.groups表包含按层次排序的组和group_member,用于存储用户所属的组.
groups --------- id parent_id name group_member --------- id group_id user_id ID PARENT_ID NAME --------------------------- 1 NULL Cerebra 2 1 CATS 3 2 CATS 2.0 4 1 Cerepedia 5 4 Cerepedia 2.0 6 1 CMS ID GROUP_ID USER_ID --------------------------- 1 1 3 2 1 4 3 1 5 4 2 7 5 2 6 6 4 6 7 5 12 8 4 9 9 1 10
我想检索给定用户的可见组.这就是说用户属于的组和这些组的子组.例如,使用以上数据:
USER VISIBLE_GROUPS 9 4, 5 3 1,2,4,5,6 12 5
我使用递归和几个数据库查询获取这些值.但我想知道是否可以使用单个SQL查询来提高我的应用程序性能.我正在使用MySQL.
我想到两件事:
1 -您可以反复将表外连接到自身,以递归方式向上走树,如下所示:
SELECT * FROM MY_GROUPS MG1 ,MY_GROUPS MG2 ,MY_GROUPS MG3 ,MY_GROUPS MG4 ,MY_GROUPS MG5 ,MY_GROUP_MEMBERS MGM WHERE MG1.PARENT_ID = MG2.UNIQID (+) AND MG1.UNIQID = MGM.GROUP_ID (+) AND MG2.PARENT_ID = MG3.UNIQID (+) AND MG3.PARENT_ID = MG4.UNIQID (+) AND MG4.PARENT_ID = MG5.UNIQID (+) AND MGM.USER_ID = 9
那会给你这样的结果:
UNIQID PARENT_ID NAME UNIQID_1 PARENT_ID_1 NAME_1 UNIQID_2 PARENT_ID_2 NAME_2 UNIQID_3 PARENT_ID_3 NAME_3 UNIQID_4 PARENT_ID_4 NAME_4 UNIQID_5 GROUP_ID USER_ID 4 2 Cerepedia 2 1 CATS 1 null Cerebra null null null null null null 8 4 9
这里的限制是您必须为要在树上行走的每个"级别"添加新的连接.如果你的树的数量少于20级,那么你可以通过创建一个显示每个用户20个级别的视图来逃避它.
2 -我所知道的唯一其他方法是创建递归数据库函数,并从代码中调用它.你仍然会有一些查询开销(也就是说,你的#查询仍然等于你在树上行走的等级数),但总体来说它应该更快,因为它全部发生在数据库中.
我不确定MySql,但在Oracle中,这样的函数与此类似(你必须更改表和字段名称;我只是复制我过去做过的事情):
CREATE OR REPLACE FUNCTION GoUpLevel(WO_ID INTEGER, UPLEVEL INTEGER) RETURN INTEGER IS BEGIN DECLARE iResult INTEGER; iParent INTEGER; BEGIN IF UPLEVEL <= 0 THEN iResult := WO_ID; ELSE SELECT PARENT_ID INTO iParent FROM WOTREE WHERE ID = WO_ID; iResult := GoUpLevel(iParent,UPLEVEL-1); --recursive END; RETURN iResult; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN NULL; END; END GoUpLevel; /