我有如下的SQL Server表结构:
ID Name ParentID
-----------------------
1 Root NULL
2 Business 1
3 Finance 1
4 Stock 3
我想在我的网页中显示详细信息,如
ID Name ParentName
-------------------------
1 Root -
2 Business Root
3 Finance Root
4 Stock Finance
如何构建SQL查询?
答案 0 :(得分:8)
试试这个......
SELECT a.ID, a.Name, b.Name AS 'ParentName'
FROM TABLE AS a LEFT JOIN TABLE AS b on a.ParentID = b.ID
使用左连接,查询将找不到要为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
答案 1 :(得分:4)
假设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
NULL的CASTing可能看起来很奇怪,但SQL Server默认将数据类型设置为INT,除非以我在查询中看到的方式指定。
答案 2 :(得分:4)
我正面临着同样的情况。 我想从同一张表中获取特定父级的所有子级列表,因为在MySQL 8以下未提供MySQL 递归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 ;
要调用此存储过程,我们需要传递3个参数,
结束数组符号。(仅附加最后一个对象而不是所有对象)。
CALL getAllChilds(1,@ ids,']');
使用此存储过程,您可能会在JSON字符串中获取所有级别的子级。 您可以解析此json字符串,并使用任何JSONparser在任何对象中进行转换。
或
我们可以将this answer包装在存储过程中,以将其用于任何编程语言(如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 ;
要调用此存储过程,我们只需要父ID。
CALL getAllChilds(1);
答案 3 :(得分:3)
SELECT CH.ID, CH.NAME, ISNULL(PA.NAME, '-') AS "PARENTNAME"
FROM TBL CH
LEFT OUTER JOIN TBL PA
ON CH.PARENTID = PA.ID
答案 4 :(得分:1)
我认为以下查询可行。我没有测试过它。
SELECT
ID
, name
, (CASE WHEN parent_name IS NULL THEN '-' ELSE parent_name END)
FROM
RELATIONS
, (SELECT
parentID
, name AS parent_name
FROM
RELATION) PARENT
WHERE
RELATIONS.parentId = PARENT.parentId
基本上,我正在做的是选择父信息,并将其与每个元组联系起来。
答案 5 :(得分:0)
这是一种简单的方法:
SELECT ID,Name,(SELECT TOP 1 Name FROM Table t WHERE t.ParentID=ParentID) AS ParentName FROM Table
答案 6 :(得分:0)
像之前发布的人一样,它需要是一个递归函数。 可能有多种情况 - 多个子节点的一个父节点(级别1层次结构) 父1有子1 父1有子2 孩子到多个孩子(2级层次结构) 等等。
我的示例有父曲线ID和子曲线ID。 例如,
WITH hierarchy AS
(select UT.parent_curve_id as origin, UT.*
from myTable UT
WHERE UT.parent_curve_id IN ( 1027455, 555)
UNION ALL
select h.origin, UT.*
from myTable UT
JOIN hierarchy h ON h.child_curve_id = UT.parent_curve_id
)
SELECT *
from hierarchy
order by unique_key