SQL Server: запуск отдельной CTE для каждой записи без курсора или функции

Приведенная таблица А с колонкой 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 ответа

Решение

Я смог найти решение. Я просто должен был сохранить оригинал 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 = ...

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

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

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

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

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

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, но (по крайней мере, в моем окружении) это намного быстрее, чем курсор.

Другие вопросы по тегам