2011-01-18 3 views
2

Моя цель - перезаписать таблицу tbl и, рекурсив через эту таблицу, выбрать аббревиатуру страны (если она существует) из другой таблицы tbl2 и добавить эти результаты вместе, которые включены в конечный результат.Помощь при рекурсивном обращении CTE к второй таблице

В примере я буду использовать придет from this post

tbl2 имеет «tbl_id» внешний ключ к ТПС и выглядит следующим образом

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

Какой вывод вы ищете, колонки и формат выборки, пожалуйста, – RichardTheKiwi

+0

вывод, который вы имеете ниже, просто отлично. –

ответ

5

Попробуйте этот пример, который даст вам выход (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 
+0

Это лучше, но я по-прежнему получаю нулевую аббревиатуру для Индии, используя ваш запрос. Обратите внимание: Индия не имеет аббревиатуры в tbl2, но я хочу, чтобы она выводила «AS», потому что Индия находится в Азии. –

+0

Вы уверены? Я вырезал и вставлял в tempdb, и я получаю 6 | Индия | 2 | Азия/Индия | AS | Азия/Индия: AS – RichardTheKiwi

+0

Вы правы! Я забыл поставить там isnull(). Теперь работает. Спасибо за помощь! –