Повторно использовать результаты из общего табличного выражения SQL Server - PullRequest
2 голосов
/ 02 апреля 2012

У меня есть запрос, чтобы получить все модули и дочерние модули для страницы, используя общее табличное выражение. Можно ли использовать результаты cte более одного раза?

пример

WITH top_level_modules (
[AppContentModuleID]
,[SortIndex]
,[ContentHolderName]
,[OwnerType]
,[AppContentModuleGuid]
,[parent_AppContentModuleID]
,[ModuleID]
,[RenderIDTag]
,[WrapperType]
,[Level]
)
AS
( 
SELECT amcp.[AppContentModuleID]
    ,amcp.[SortIndex]
    ,amcp.[ContentHolderName]
    ,1
    ,amc.[AppContentModuleGuid]
    ,amc.[parent_AppContentModuleID]
    ,amc.[ModuleID]
    ,amc.[RenderIDTag]
    ,amc.[WrapperType]
    ,0 AS [Level]
FROM [dbo].[application_module_content_page] amcp
INNER JOIN [dbo].[application_module_content] amc on amcp.[AppContentModuleID] = amc.[AppContentModuleID]
WHERE amcp.[PageID] = @PageID
UNION
SELECT amcm.[AppContentModuleID]
    ,amcm.[SortIndex]
    ,amcm.[ContentHolderName]
    ,2
    ,amc.[AppContentModuleGuid]
    ,amc.[parent_AppContentModuleID]
    ,amc.[ModuleID]
    ,amc.[RenderIDTag]
    ,amc.[WrapperType]
    ,0
FROM [dbo].[application_module_content_masterpage] amcm
INNER JOIN [dbo].[application_module_content] amc on amcm.[AppContentModuleID] = amc.[AppContentModuleID]
WHERE amcm.[AppMasterPageID] = @MasterPageID
),
child_modules AS 
(
SELECT tlm.[AppContentModuleID]
    ,tlm.[SortIndex]
    ,tlm.[ContentHolderName]
    ,tlm.[OwnerType]
    ,tlm.[AppContentModuleGuid]
    ,tlm.[parent_AppContentModuleID]
    ,tlm.[ModuleID]
    ,tlm.[RenderIDTag]
    ,tlm.[WrapperType]
    ,tlm.[Level]
FROM top_level_modules tlm
UNION ALL
SELECT 
    amc.[AppContentModuleID]
    ,CASE WHEN amc.[SortIndex] IS NULL THEN tlm.[SortIndex] ELSE amc.[SortIndex] END
    ,null
    ,3
    ,amc.[AppContentModuleGuid]
    ,amc.[parent_AppContentModuleID]
    ,amc.[ModuleID]
    ,amc.[RenderIDTag]
    ,amc.[WrapperType]
    ,[Level] + 1 AS [Level]
FROM [dbo].[application_module_content] amc
INNER JOIN child_modules tlm on tlm.[AppContentModuleID] = amc.[parent_AppContentModuleID]
)
SELECT * 
FROM child_modules cm
ORDER BY cm.[OwnerType]
, cm.[Level]
, cm.[SortIndex]

SELECT apcs.[StyleType] 
    ,apcs.[StyleName]
    ,apcs.[StyleValue]
FROM child_modules cm
INNER JOIN dbo.[application_module_content_style] apcs 
on cm.AppContentMdouleID = apcs.AppContentMdouleID

Первый выбор работает, но второй выбор выдает ошибку «Неверное имя объекта 'child_modules'."

Ответы [ 3 ]

10 голосов
/ 02 апреля 2012

С WITH common_table_expression руководство :

Указывает временный именованный набор результатов, известный как общее табличное выражение (CTE).Он получен из простого запроса и , определенного в области выполнения оператора single SELECT, INSERT, UPDATE или DELETE .

Итак, нетВы не можете расширить область действия CTE за пределы оператора SELECT, в котором он был определен. Вам нужно будет сохранить результат во временной таблице или табличной переменной, если вы хотите использовать результат более одного раза.

2 голосов
/ 02 апреля 2012

Вам потребуется разделить CTE child_modules на два CTE.

Первый содержит первый SELECT текущего CTE child_modules, затем использует второй CTE, который основан на child_modules.

Тогда ваш последний SELECT будет использовать третий CTE вместо child_modules.

0 голосов
/ 22 мая 2014

Используйте как следует:

Create FUNCTION [dbo].[fnGetAllData] 
(
    @UserId int    
)
RETURNS TABLE
AS
RETURN  
(
    WITH UserPRecursive AS
    (   
    SELECT u.userid,u.OverrideID
    FROM UserOverride u where OverrideID=@UserId
    UNION ALL
    SELECT C.userid,C.OverrideID
    FROM UserOverride AS C INNER JOIN UserPRecursive AS cr
    ON C.OverrideID = cr.userid 
    )   
    , UserCRecursive AS
    (   
    SELECT u.userid,u.OverrideID
    FROM UserOverride u where UserID=@UserId
    UNION ALL
    SELECT C.userid,C.OverrideID
    FROM UserOverride AS C INNER JOIN UserCRecursive AS cr
    ON C.userid = cr.OverrideID 
    )
    SELECT distinct CR1.userid as userId FROM UserPRecursive AS CR1
    UNION ALL
    SELECT distinct cr2.OverrideID as userId FROM UserCRecursive AS CR2 
    UNION ALL
    select userid from [User] where UserID=@UserId
)
...