kir*_*mal 7 sql t-sql sql-server
我有如下的sql server表结构:
ID Name ParentID
-----------------------
1 Root NULL
2 Business 1
3 Finance 1
4 Stock 3
Run Code Online (Sandbox Code Playgroud)
我想在我的网页中显示详细信息
ID Name ParentName
-------------------------
1 Root -
2 Business Root
3 Finance Root
4 Stock Finance
Run Code Online (Sandbox Code Playgroud)
如何构建我的SQL查询?请帮我.
Eri*_*ric 10
试试这个...
SELECT a.ID, a.Name, b.Name AS 'ParentName'
FROM TABLE AS a LEFT JOIN TABLE AS b on a.ParentID = b.ID
Run Code Online (Sandbox Code Playgroud)
使用左连接,查询将找不到要为NULL加入的任何内容并为ParentName
列返回空白.
编辑:
如果您不希望"父级"列为空,但希望显示" - "破折号,请使用此查询.
SELECT a.ID, a.Name, COALESCE(b.Name,'-') AS 'ParentName'
FROM TABLE AS a LEFT JOIN TABLE AS b on a.ParentID = b.ID
Run Code Online (Sandbox Code Playgroud)
假设 SQL Server 2005+,使用这样的递归 CTE:
WITH hierarchy AS (
SELECT t.id,
t.name,
t.parentid,
CAST(NULL AS VARCHAR(50)) AS parentname
FROM YOUR_TABLE t
WHERE t.parentid IS NULL
UNION ALL
SELECT x.id,
x.name,
x.parentid,
y.name
FROM YOUR_TABLE x
JOIN hierarchy y ON y.id = x.parentid)
SELECT s.id,
s.name,
s.parentname
FROM hierarchy s
Run Code Online (Sandbox Code Playgroud)
NULL 的 CASTing 可能看起来很奇怪,但 SQL Server 将数据类型默认为 INT,除非以您在我的查询中看到的方式指定。
我面临着同样的情况。我想从同一个表中获取特定父级的所有子列表,因为 MySQL在 MySQL 8 以下没有提供递归 CTE 。
我已经通过递归存储过程解决了我的问题。我们需要将max_sp_recursion_depth设置为递归存储过程调用。
我的表结构如下
我的存储过程(带递归)如下:
DROP PROCEDURE IF EXISTS getAllChilds;
DELIMITER $$
SET @@SESSION.max_sp_recursion_depth=25; $$
CREATE PROCEDURE getAllChilds (IN inId int(11), INOUT list_obj text, IN end_arr CHAR(1))
BEGIN
DECLARE stop_cur INTEGER DEFAULT 0;
DECLARE _id INTEGER DEFAULT 0;
DECLARE _name VARCHAR(20) DEFAULT 0;
DEClARE curSelfId CURSOR FOR SELECT id, name FROM new_table where parentId = inId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET stop_cur = 1;
OPEN curSelfId;
getSelfId: LOOP
FETCH curSelfId INTO _id, _name;
IF stop_cur = 1 THEN LEAVE getSelfId; END IF;
IF list_obj is null or list_obj = "" then
SET list_obj = CONCAT("[","{",'"name":"',_name,'","id":"',_id,'"',"}");
else
SET list_obj = CONCAT(list_obj,',', "{",'"name":"',_name,'","id":"',_id,'"',"}");
end if;
CALL getAllChilds(_id,list_obj,"");
END LOOP getSelfId;
CLOSE curSelfId;
IF end_arr is not null and end_arr != "" then
SET list_obj = CONCAT(list_obj,end_arr);
SELECT @ids;
end if;
END$$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
要调用这个存储过程,我们需要传递 3 个参数,
结束数组符号。(仅附加最后一个对象而不是所有对象)。
调用 getAllChilds(1,@ids,']');
使用此存储过程,您可以获取 JSON 字符串中的所有级别子级。您可以解析此 json 字符串并使用任何 JSONparser 在任何对象中进行转换。
或者
我们可以将这个答案包装在存储过程中,以便将其用于任何编程语言,例如 JAVA。我们将其包装到存储过程中,因为我们不能在查询中使用:=。这里我们使用find_in_set函数。我的存储过程(没有递归)。
DROP PROCEDURE IF EXISTS getAllChilds;
DELIMITER $$
CREATE PROCEDURE getAllChilds (IN inId int(11))
BEGIN
select id,
name,
parentid
from
(select * from new_table
order by parentid, id) new_table,
(select @pv := inId) initialisation
where
find_in_set(parentid, @pv) > 0
and @pv := concat(@pv, ',', id);
END$$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
要调用此存储过程,我们只需要父 ID。
CALL getAllChilds(1);
Run Code Online (Sandbox Code Playgroud)