SQL Server: запуск отдельной CTE для каждой записи без курсора или функции - PullRequest
0 голосов
/ 29 октября 2018

Дана таблица A со столбцом LocationID и множеством записей,

Можно ли полностью запустить CTE для каждой записи без использования курсора (во время цикла выборки) или функции (через перекрестное применение)?

Я не могу запустить CTE из таблицы A, потому что CTE будет подробно изучать иерархическую таблицу parent-child (ParentID, ChildID), чтобы найти всех потомков определенного типа для каждого LocationID таблицы A. Кажется, что если я сделаю CTE, используя таблицу A, он будет смешивать дочерние элементы всех LocationID в таблице A.

По сути, мне нужно отдельно запустить CTE для каждого LocationID таблицы A и поместить в таблицу со столбцами LocationID и ChildID (LocationID - те, что из таблицы A, а ChildID - потомки определенного типа, найденного через CTE) .

Ответы [ 3 ]

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

Вы можете сделать что-то вроде этого:

Declare @LocationID As Int
Select
    LocationID
    , 0 as Processed
Into #Temp_Table
From TableA

While Exists (Select Top 1 1 From #Temp_Table Where Processed = 0)
Begin
    Select Top 1 @LocationID = LocationID
    From #Temp_Table 
    Where Processed = 0
    Order By LocationID

    /*  Do your processing here */

    Update #Temp_Table Set
        Processed = 0
    Where LocationID = @LocationID
End

Это все еще RBAR, но (по крайней мере, в моем окружении) это намного быстрее, чем курсор.

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

Мне удалось найти решение. Мне просто нужно было сохранить исходную LocationID в качестве ссылки, а затем в результатах CTE, которые будут включать все возможные записи по мере углубления в список, я применяю фильтр, который мне нужен. Да, все записи смешаны в результатах, однако, поскольку ссылка на LocationID исходной таблицы была сохранена (как OriginalParentID), я все еще могу получить ее.

;WITH CTE AS
(
    --Original list of parents
    SELECT a.LocationID AS OriginalParentID, l.ParentID, l.ChildID, l.ChildType
    FROM TableA a
    INNER JOIN tblLocationHierarchy l ON l.ParentID = a.LocationID

    UNION ALL

    --Getting all descendants of the original list of parents
    SELECT CTE.OriginalParentID, l.ParentID, l.ChildID, l.ChildType
    FROM tblLocationHierarchy l
    INNER JOIN CTE ON CTE.ChildID = l.ParentID
)
SELECT OriginalParentID, ChildID
FROM CTE
--Filtering is done here
WHERE ChildType = ...
0 голосов
/ 29 октября 2018

Это ваш основной макет.

;with CTE AS
(
   select .......
)

select *
from CTE
cross apply (select distinct Location from TableA) a
where CTE.Location=a.Location

Некоторые примеры данных и ожидаемые результаты обеспечат лучший ответ.

...