我的桌面设计是
users (id, username..., parent_id)
数据
id username parent_id
-------------------------------
1 | admin | null
2 | reseller 1 | 1
3 | client 1 | 1
4 | reseller 2 | 1
5 | reseller 3 | 2
6 | reseller 4 | 2
7 | client 2 | 5
8 | client 3 | 6
我希望得到id
1
我研究过Adjacency List,Nested List&关闭表设计,但得出的结论是基于会话的邻接列表在我的情况下会更好。
我在Hierarchical queries in MySQL
找到了一个例子SELECT @id :=
(
SELECT senderid
FROM mytable
WHERE receiverid = @id
) AS person
FROM (
SELECT @id := 5
) vars
STRAIGHT_JOIN
mytable
WHERE @id IS NOT NULL
我尝试修改此查询以获取此结果
SELECT group_concat(@id :=
(
SELECT id
FROM users
WHERE parent_id = @id
)) AS u
FROM (
SELECT @id := 1
) vars
STRAIGHT_JOIN
users
WHERE @id IS NOT NULL
但它不起作用。这是SQLFiddle
需要帮助才能使查询正常工作。
这不是How to do the Recursive SELECT query in MySQL?的重复,因为它处理父和子之间的一对多关系,而one-to = many关系在查询中创建问题。
答案 0 :(得分:0)
DELIMITER $$
DROP FUNCTION IF EXISTS `siblings` $$
CREATE FUNCTION `siblings` (GivenID INT) RETURNS varchar(1024) CHARSET latin1
DETERMINISTIC
BEGIN
DECLARE rv,q,queue,queue_children VARCHAR(1024);
DECLARE queue_length,front_id,pos INT;
SET rv = '';
SET queue = GivenID;
SET queue_length = 1;
WHILE queue_length > 0 DO
SET front_id = FORMAT(queue,0);
IF queue_length = 1 THEN
SET queue = '';
ELSE
SET pos = LOCATE(',',queue) + 1;
SET q = SUBSTR(queue,pos);
SET queue = q;
END IF;
SET queue_length = queue_length - 1;
SELECT IFNULL(qc,'') INTO queue_children
FROM (SELECT GROUP_CONCAT(id) qc
FROM `users` WHERE parent_id = front_id) A;
IF LENGTH(queue_children) = 0 THEN
IF LENGTH(queue) = 0 THEN
SET queue_length = 0;
END IF;
ELSE
IF LENGTH(rv) = 0 THEN
SET rv = queue_children;
ELSE
SET rv = CONCAT(rv,',',queue_children);
END IF;
IF LENGTH(queue) = 0 THEN
SET queue = queue_children;
ELSE
SET queue = CONCAT(queue,',',queue_children);
END IF;
SET queue_length = LENGTH(queue) - LENGTH(REPLACE(queue,',','')) + 1;
END IF;
END WHILE;
RETURN rv;
END $$
然后,为了获得父母的兄弟姐妹/孩子,使用上面创建的函数siblings
进行简单的调用就足够了。
SELECT siblings(id) AS `siblings` from `users` where `id` = 1
这会将结果返回为
siblings
---------------
2,3,4,5,6,7,8