T-SQL CTE, чтобы получить родителя - PullRequest
0 голосов
/ 25 октября 2018

Я пытался проработать некоторые примеры, опубликованные на сайте, но, похоже, нигде не смог применить их к моей проблеме.

У меня есть таблица, которая содержит значения списка,с этими значениями могут быть связаны разные родители, которые находятся в одной таблице.К сожалению, это таблица, предоставленная системой, поэтому я не могу вносить какие-либо изменения в ее работу.

Вот пример набора данных из моей таблицы EnumType

EnumTypeID     ParentEnumTypeID
1              Null
2              1
3              2
4              3
5              2
6              3
7              1
8              7

Что я пытаюсь сделатьнужно найти конечную парентенум любого потомка, где 1 - максимальное значение иерархии (в системе 1 - корневой список, все значения являются потомками 1).Таким образом, для любого предоставленного идентификатора я должен быть в состоянии получить самый верхний из указанных родителей, у которого их собственный родитель равен 1 (т.е. всегда возвращать второй самый верхний слой, где enumtypeID имеет родителя = 1).Например, для enumtypeid 6 должен возвращаться parentenumtypeid 2, для enumtypeid 8 должен возвращаться 7 и т. Д. У меня уже было что-то ранее, но похоже, что он возвращает следующий слой вверх, а не корневое значение

WITH cte (enumtypeid, parentenumtypeid) AS
(
SELECT EnumTypeId,ParentEnumTypeId FROM EnumType WITH (NOLOCK)

UNION ALL
SELECT
e.enumtypeid, e.parentenumtypeid
FROM EnumType e
INNER JOIN cte ON cte.parentenumtypeid=e.EnumTypeId
WHERE e.ParentEnumTypeId IS NULL AND e.ParentEnumTypeId != '1'
)

Toдобавьте некоторый дополнительный контекст к этому, вот мой полный SQL.Запрос является частью более широкого запроса для получения некоторых деталей запроса на изменение из моей базы данных службы поддержки.

declare @planguagecode nvarchar(3) = 'ENU'
declare @putcoffset int = 1

WITH ChangeEnum (enumtypeid, parentenumtypeid) AS
(
SELECT EnumTypeId,ParentEnumTypeId FROM EnumType WITH (NOLOCK)

UNION ALL
SELECT
e.enumtypeid, e.parentenumtypeid
FROM EnumType e
INNER JOIN ChangeEnum ON ChangeEnum.parentenumtypeid=e.EnumTypeId
WHERE e.ParentEnumTypeId IS NULL AND e.ParentEnumTypeId != '28F88C04-D11D-78C0-A237-FA9ABD6C6478'
)
SELECT DISTINCT
crq.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C as 'id', 
crq.Title_9691DD10_7211_C835_E3E7_6B38AF8B8104 as 'title', 
COALESCE(sds.DisplayName, 'No Status') as 'status', 
COALESCE(cds.DisplayName, 'Uncategorised') as 'category', 
COALESCE(ads.DisplayName, 'Not Assigned') as 'area', 
COALESCE(rds.DisplayName,'Not Assessed') as 'risk', 
COALESCE(pds.DisplayName,'Not Assigned') as 'priority', 
COALESCE(CASE WHEN rads.DisplayName != ads.DisplayName THEN RADS.DisplayName ELSE ADS.Displayname END,'Not Assigned') as 'rootarea',
CONVERT(VARCHAR(16),DATEADD(mi, @pUTCOffset, crq.CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688),120) as 'created',
CONVERT(VARCHAR(16),DATEADD(mi, @pUTCOffset, crq.ScheduledStartDate_89429D01_365C_366D_FCDA_3198102B180C),120) as 'start', 
CONVERT(VARCHAR(16),DATEADD(mi, @pUTCOffset, crq.ScheduledEndDate_6FC72C26_565D_CB2A_BBAF_6A699C15FE99),120) as 'end'
FROM MTV_System$WorkItem$ChangeRequest crq WITH (NOLOCK)
LEFT JOIN DisplayStringView rds WITH (NOLOCK) ON crq.Risk_B9DCB168_B698_6864_E562_08F986C1D4E0 = rds.LTStringId AND rds.LanguageCode = @pLanguageCode
LEFT JOIN DisplayStringView ads WITH (NOLOCK) ON crq.Area_BC1C6C5B_F242_D568_BE10_FC23CD14655A = ads.LTStringId AND ads.LanguageCode = @pLanguageCode
LEFT JOIN DisplayStringView sds WITH (NOLOCK) ON crq.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = sds.LTStringID AND sds.LanguageCode = @pLanguageCode
LEFT JOIN DisplayStringView cds WITH (NOLOCK) ON crq.Category_7B1892FE_108A_EC85_064D_7815C2DFC442 = cds.LTStringID AND cds.LanguageCode = @pLanguageCode
LEFT JOIN DisplayStringView pds WITH (NOLOCK) ON crq.Priority_B1226A17_0705_8F13_1ED4_74A38D2E1707 = pds.LTStringId AND pds.LanguageCode = @pLanguageCode
LEFT JOIN ChangeEnum ce on crq.Area_BC1C6C5B_F242_D568_BE10_FC23CD14655A=ce.enumtypeid
LEFT JOIN DisplayStringView rads WITH (NOLOCK) ON ce.parentenumtypeid = RADS.LTStringId AND RADS.LanguageCode = @pLanguageCode AND RADS.LTStringId ! ='28F88C04-D11D-78C0-A237-FA9ABD6C6478'
WHERE 
    crq.ScheduledStartDate_89429D01_365C_366D_FCDA_3198102B180C IS NOT NULL /* Scheduled */ AND 
    crq.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = '6d6c64dd-07ac-aaf5-f812-6a7cceb5154d' /* In Progress */

Итак, подведем итог. Мне нужно получить самый верхний родительский идентификатор ребенка, у которого родительский идентификатор равен 1.В этом случае родительский элемент 1, у которого нет родительского элемента, является просто заполнителем таблицы.Дочерние идентификаторы предоставляются по запросу выше из другой таблицы.

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Далее показано использование общего табличного выражения (CTE) для обхода дерева при отслеживании первого уровня дочерних элементов ниже корня.

-- Sample data.
declare @Enums as Table ( EnumTypeId Int Identity, ParentEnumTypeId Int );
insert into @Enums ( ParentEnumTypeId ) values
  ( NULL ), ( 1 ), ( 2 ), ( 3 ), ( 2 ), ( 3 ), ( 1 ), ( 7 );
select * from @Enums;

-- Walk the tree tracking the parentage.
with
  Enums as (
    -- Start at the roots which have a   NULL   parent.
    select EnumTypeId, ParentEnumTypeId, Cast( NULL as Int ) as PenultimateParentEnumTypeId, 0 as Depth
      from @Enums
      where ParentEnumTypeId is NULL
    union all
    -- Add each level of leaves.
    select CE.EnumTypeId, CE.ParentEnumTypeId,
      -- If the parent has no parent or, equivalently, the parent's depth is zero, then capture the
      --   child's   EnumTypeId .
      case when E.ParentEnumTypeId is NULL then CE.EnumTypeId else PenultimateParentEnumTypeId end,
      -- case when E.Depth = 0 then CE.EnumTypeId else PenultimateParentEnumTypeId end,
      E.Depth + 1
      from Enums as E inner join
        @Enums as CE on CE.ParentEnumTypeId = E.EnumTypeId )
  -- Output the results.
  select EnumTypeId, ParentEnumTypeId, PenultimateParentEnumTypeId, Depth
    from Enums
    order by EnumTypeId;
0 голосов
/ 25 октября 2018

Это работает для предоставленного примера таблицы.Я использую 6 для демострации

declare @leaf int = 6

while exists (select * from enums where parentenumtypeid <> 1 and enumtypeid = @leaf)
    select @leaf = parentenumtypeid from enums where enumtypeid = @leaf;
    print @leaf;

РЕДАКТИРОВАТЬ

    CREATE FUNCTION FindCustomParent (@input VARCHAR(250))
RETURNS VARCHAR(250)
AS BEGIN
    declare @output int
    set @output = @input

while exists (select * from ChangeEnum where parentenumtypeid <> '28F88C04-D11D-78C0-A237-FA9ABD6C6478' and enumtypeid = @output)
    select @output = parentenumtypeid from ChangeEnum where enumtypeid = @output;
    return @output
END


    SELECT DISTINCT
    crq.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C as 'id', 
    crq.Title_9691DD10_7211_C835_E3E7_6B38AF8B8104 as 'title', 
    COALESCE(sds.DisplayName, 'No Status') as 'status', 
    COALESCE(cds.DisplayName, 'Uncategorised') as 'category', 
    COALESCE(ads.DisplayName, 'Not Assigned') as 'area', 
    COALESCE(rds.DisplayName,'Not Assessed') as 'risk', 
    COALESCE(pds.DisplayName,'Not Assigned') as 'priority', 
    COALESCE(CASE WHEN rads.DisplayName != ads.DisplayName THEN RADS.DisplayName ELSE ADS.Displayname END,'Not Assigned') as 'rootarea',
    CONVERT(VARCHAR(16),DATEADD(mi, @pUTCOffset, crq.CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688),120) as 'created',
    CONVERT(VARCHAR(16),DATEADD(mi, @pUTCOffset, crq.ScheduledStartDate_89429D01_365C_366D_FCDA_3198102B180C),120) as 'start', 
    CONVERT(VARCHAR(16),DATEADD(mi, @pUTCOffset, crq.ScheduledEndDate_6FC72C26_565D_CB2A_BBAF_6A699C15FE99),120) as 'end',

    dbo.FindFirstParent(crq.Area_BC1C6C5B_F242_D568_BE10_FC23CD14655A) as Parent

    FROM MTV_System$WorkItem$ChangeRequest crq WITH (NOLOCK)
    LEFT JOIN DisplayStringView rds WITH (NOLOCK) ON crq.Risk_B9DCB168_B698_6864_E562_08F986C1D4E0 = rds.LTStringId AND rds.LanguageCode = @pLanguageCode
    LEFT JOIN DisplayStringView ads WITH (NOLOCK) ON crq.Area_BC1C6C5B_F242_D568_BE10_FC23CD14655A = ads.LTStringId AND ads.LanguageCode = @pLanguageCode
    LEFT JOIN DisplayStringView sds WITH (NOLOCK) ON crq.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = sds.LTStringID AND sds.LanguageCode = @pLanguageCode
    LEFT JOIN DisplayStringView cds WITH (NOLOCK) ON crq.Category_7B1892FE_108A_EC85_064D_7815C2DFC442 = cds.LTStringID AND cds.LanguageCode = @pLanguageCode
    LEFT JOIN DisplayStringView pds WITH (NOLOCK) ON crq.Priority_B1226A17_0705_8F13_1ED4_74A38D2E1707 = pds.LTStringId AND pds.LanguageCode = @pLanguageCode
    LEFT JOIN ChangeEnum ce on crq.Area_BC1C6C5B_F242_D568_BE10_FC23CD14655A=ce.enumtypeid
    LEFT JOIN DisplayStringView rads WITH (NOLOCK) ON ce.parentenumtypeid = RADS.LTStringId AND RADS.LanguageCode = @pLanguageCode AND RADS.LTStringId ! ='28F88C04-D11D-78C0-A237-FA9ABD6C6478'
    WHERE 
        crq.ScheduledStartDate_89429D01_365C_366D_FCDA_3198102B180C IS NOT NULL /* Scheduled */ AND 
        crq.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = '6d6c64dd-07ac-aaf5-f812-6a7cceb5154d' /* In Progress */
...