我的目标是通过表tbl递归,并在通过该表递归时从另一个表tbl2中选择一个国家缩写(如果存在),并将这些结果附加到最终输出中。
我将使用的示例将来from this post
tbl2有一个外键'tbl_id'到tbl,看起来像这样
INSERT INTO @tbl2( Id, Abbreviation, tbl_id )
VALUES
(100, 'EU', 1)
,(101, 'AS', 2)
,(102, 'DE', 3)
,(103, 'CN', 5)
*注意:并非所有国家/地区都有缩写。
诀窍是,我希望亚洲所有国家至少显示亚洲的缩写“AS”,即使一个国家没有缩写(例如印度)。如果该国家的缩写,则结果需要如下所示:中国:CN,AS
我使用子查询部分工作,但是印度总是为缩写返回NULL。它的行为就像没有完整的递归路径回到缩写,然后它返回null。也许解决方案是在缩写表上使用左外连接?我已经尝试了几个小时的许多不同的变化,子查询尽可能接近我。
WITH abcd
AS (
-- anchor
SELECT id, [Name], ParentID,
CAST(([Name]) AS VARCHAR(1000)) AS "Path"
FROM @tbl
WHERE ParentId IS NULL
UNION ALL
--recursive member
SELECT t.id, t.[Name], t.ParentID,
CAST((a.path + '/' + t.Name + ':' +
(
select t2.abbreviation + ','
from @tbl2
where t.id = t2.id
)) AS VARCHAR(1000)) AS "Path"
FROM @tbl AS t
JOIN abcd AS a
ON t.ParentId = a.id
)
SELECT * FROM abcd
不过,如果重要的话,我正在使用sql server 2005
答案 0 :(得分:6)
试试这个例子,它会给你输出(1个样本行)
id Name ParentID Path abbreviation (No column name)
5 China 2 Asia/China CN,AS Asia/China:CN,AS
TSQL正在
DECLARE @tbl TABLE (
Id INT
,[Name] VARCHAR(20)
,ParentId INT
)
INSERT INTO @tbl( Id, Name, ParentId )
VALUES
(1, 'Europe', NULL)
,(2, 'Asia', NULL)
,(3, 'Germany', 1)
,(4, 'UK', 1)
,(5, 'China', 2)
,(6, 'India', 2)
,(7, 'Scotland', 4)
,(8, 'Edinburgh', 7)
,(9, 'Leith', 8)
;
DECLARE @tbl2 table (id int, abbreviation varchar(10), tbl_id int)
INSERT INTO @tbl2( Id, Abbreviation, tbl_id )
VALUES
(100, 'EU', 1)
,(101, 'AS', 2)
,(102, 'DE', 3)
,(103, 'CN', 5)
;WITH abbr AS (
SELECT a.*, isnull(b.abbreviation,'') abbreviation
FROM @tbl a
left join @tbl2 b on a.Id = b.tbl_id
), abcd AS (
-- anchor
SELECT id, [Name], ParentID,
CAST(([Name]) AS VARCHAR(1000)) [Path],
cast(abbreviation as varchar(max)) abbreviation
FROM abbr
WHERE ParentId IS NULL
UNION ALL
--recursive member
SELECT t.id, t.[Name], t.ParentID,
CAST((a.path + '/' + t.Name) AS VARCHAR(1000)) [Path],
isnull(nullif(t.abbreviation,'')+',', '') + a.abbreviation
FROM abbr AS t
JOIN abcd AS a
ON t.ParentId = a.id
)
SELECT *, [Path] + ':' + abbreviation
FROM abcd