【问题标题】:Help with recursive CTE query joining to a second table帮助递归 CTE 查询加入第二个表
【发布时间】:2011-01-18 02:39:10
【问题描述】:

我的目标是通过表 tbl 进行递归,并在通过该表进行递归时从另一个表 tbl2 中选择一个国家/地区缩写(如果存在)并将这些结果附加在一起,这些结果将包含在最终输出中。

我将使用的示例将来自from this post

tbl2 有一个指向 tbl 的外键 'tbl_id',看起来像这样

INSERT INTO @tbl2( Id, Abbreviation, tbl_id ) 
VALUES 
 (100, 'EU', 1) 
,(101, 'AS', 2) 
,(102, 'DE', 3) 
,(103, 'CN', 5)

*注意:并非所有国家都有缩写。

诀窍是,我希望亚洲的所有国家/地区至少显示亚洲的缩写,即“AS”,即使一个国家/地区没有缩写(例如印度)。如果国家/地区确实有缩写结果需要如下所示:China:CN,AS

我已经使用子查询部分地工作了,但是 India 总是返回 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

【问题讨论】:

  • 你在寻找什么输出,列和示例格式请
  • 你下面的输出就好了。

标签: sql sql-server-2005 subquery recursive-query


【解决方案1】:

试试这个例子,它会给你输出(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 

【讨论】:

  • 这样更好,但我仍然使用您的查询得到印度的空缩写。请注意,印度在 tbl2 中没有缩写,但我希望它输出“AS”,因为印度在亚洲。
  • 你确定吗?我剪切并粘贴到 tempdb 中,得到 6 |印度 | 2 |亚洲/印度 |作为 |亚洲/印度:AS
  • 你是对的!我忘了在里面放一个 isnull() 。它现在正在工作。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2014-03-19
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多