2011-12-06 12 views
11

È possibile eseguire una sottomissione JOIN contro un'espressione di tabella comune? Se no, allora qualcuno può farmi sapere come eseguire ciò che sto cercando di fare sotto? Gli esempi sarebbero eccellenti.T-SQL JOIN contro una Common Table Expression (CTE)

Ad esempio:

LEFT JOIN (

      ;WITH [UserDefined] 
       AS (SELECT *, -- Make sure we get only the latest revision. 
         ROW_NUMBER() OVER (PARTITION BY [ID] 
               ORDER BY [RevisionNumber] DESC) AS RN 
        FROM [syn_Change]) 

      SELECT [UserDefined].[ID] 
       ,[UserDefined].[ChangeNumber] 
       ,[UserDefined].[Usr_CoResponsibility] 
       ,[UserDefined].[Usr_StarFlowStatus] 

      FROM [UserDefined] 
      WHERE (RN = 1) 

      ) [UserColumns] 
ON [UserColumns].[ChangeNumber] = [CTE].[ChangeNumber] 

Ecco la mia query full:

;WITH CTE 
    AS (SELECT *, -- Make sure we get only the latest revision. 
      ROW_NUMBER() OVER (PARTITION BY [ItemID] 
            ORDER BY [RevisionNumber] DESC) AS RN 
     FROM [dw_Change]) 

SELECT [CTE].[ItemID] 
     ,[CTE].[ViewID] 
     ,[CTE].[FolderItemID] 
     ,[CTE].[RevisionNumber] 
     ,[CTE].[ChangeNumber] 
     ,[CTE].[Synopsis] 
     ,[CTE].[Description] 
     ,[CTE].[EnteredOn] 
     ,[CTE].[Responsibility] 
     --,[UserColumns].[Usr_CoResponsibility] 
     --,[UserColumns].[Usr_StarFlowStatus] 
     ,[CTE].[Status] -- This will display the human name on the front-end with code. 
     ,[Users].[F7] AS [ResponsibilityName] 
     ,[GroupName].[Name] AS [AppGroupName] 
     ,[AppName].[Name] AS [AppName] 
FROM CTE 
LEFT JOIN [S3] [Users] ON [Users].[F0] = [CTE].[Responsibility] 
LEFT JOIN (SELECT [Name], [ViewID] 
      FROM [dw_Folder] 
      WHERE ([FolderItemID] = -1)) [GroupName] 
ON [GroupName].[ViewID] = [CTE].[ViewID] 

LEFT JOIN (SELECT [Name], [ItemID] 
      FROM [dw_Folder] 
      WHERE ([FolderItemID] <> -1)) [AppName] 
ON [AppName].[ItemID] = [CTE].[FolderItemID] 

LEFT JOIN (

      ;WITH [UserDefined] 
       AS (SELECT *, -- Make sure we get only the latest revision. 
         ROW_NUMBER() OVER (PARTITION BY [ID] 
               ORDER BY [RevisionNumber] DESC) AS RN 
        FROM [syn_Change]) 

      SELECT [UserDefined].[ID] 
       ,[UserDefined].[ChangeNumber] 
       ,[UserDefined].[Usr_CoResponsibility] 
       ,[UserDefined].[Usr_StarFlowStatus] 

      FROM [UserDefined] 
      WHERE (RN = 1) 

      ) [UserColumns] 
ON [UserColumns].[ChangeNumber] = [CTE].[ChangeNumber] 

WHERE (RN = 1) 

Grazie mille!

risposta

30

Quando si definisce un CTE lo si sta facendo prima del resto della query. Così non si può scrivere:

LEFT JOIN (
    ;WITH CTE 
    ... 
) 

Come un rapido a parte, il motivo per gente mette ; davanti WITH è perché tutte le precedenti dichiarazioni devono essere terminati. Se gli sviluppatori potessero prendere l'abitudine di terminare tutte le istruzioni SQL con ; allora non sarebbe necessario, ma sto divagando ...

È possibile scrivere più CTE in questo modo:

WITH SomeCTE AS (
    SELECT ... 
    FROM ... 
), AnotherCTE AS (
    SELECT ... 
    FROM ... 
) 
SELECT * 
FROM SomeCTE LEFT JOIN 
    AnotherCTE ON ... 
; 
+6

E finché un CTE viene definito prima degli altri, è possibile fare riferimento alle CTE che seguono. – Bora

1

È possibile avere più CTE, credo; devi solo metterli entrambi in cima.

Vedi here:

È possibile, tuttavia, definire più CTE dopo la parola chiave WITH separando ogni CTE con una virgola.

2

Se si dispone di più CTE, hanno bisogno di essere all'inizio della sua dichiarazione (separati da virgole, e solo uno ;WITH per iniziare l'elenco dei CTE):

;WITH CTE AS (......), 
[UserDefined] AS (.......) 
SELECT..... 

e poi si può utilizzare entrambi (o anche più di due) nell'istruzione SELECT.

3

È necessario prima dichiarare più CTE. Esempio:

WITH CTE_1 AS 
(
    .... 
), 
CTE_2 AS 
(
    ... 
) 

SELECT  * 
FROM   FOO 
LEFT JOIN  CTE_1 
LEFT JOIN  CTE_2 
1
; 
WITH 
    RANKED_CTE AS 
(
    SELECT 
    *, 
    ROW_NUMBER() OVER (PARTITION BY [ItemID] ORDER BY [RevisionNumber] DESC) AS RN 
    FROM 
    [dw_Change] 
) 
, 
    CTE AS 
(
    SELECT 
    * 
    FROM 
    RANKED_CTE 
    WHERE 
    RN = 1 
) 
, 
    GroupName AS 
(
    SELECT 
    [Name], [ViewID] 
    FROM 
    [dw_Folder] 
    WHERE 
    ([FolderItemID] = -1) 
) 
, 
    AppName AS 
(
    SELECT 
    [Name], [ItemID] 
    FROM 
    [dw_Folder] 
    WHERE 
    ([FolderItemID] <> -1) 
) 
SELECT [CTE].[ItemID] 
     ,[CTE].[ViewID] 
     ,[CTE].[FolderItemID] 
     ,[CTE].[RevisionNumber] 
     ,[CTE].[ChangeNumber] 
     ,[CTE].[Synopsis] 
     ,[CTE].[Description] 
     ,[CTE].[EnteredOn] 
     ,[CTE].[Responsibility] 
     --,[UserColumns].[Usr_CoResponsibility] 
     --,[UserColumns].[Usr_StarFlowStatus] 
     ,[CTE].[Status] -- This will display the human name on the front-end with code. 
     ,[Users].[F7] AS [ResponsibilityName] 
     ,[GroupName].[Name] AS [AppGroupName] 
     ,[AppName].[Name] AS [AppName] 
FROM 
      CTE 
LEFT JOIN [S3] [Users] ON [Users].[F0] = [CTE].[Responsibility] 
LEFT JOIN [GroupName] ON [GroupName].[ViewID] = [CTE].[ViewID] 
LEFT JOIN [AppName]  ON [AppName].[ItemID] = [CTE].[FolderItemID] 
Problemi correlati