2011-12-06 15 views
11

¿Es posible realizar una subconsulta JOIN contra una Expresión de tabla común? Si no, ¿alguien me puede decir cómo realizar lo que estoy tratando de hacer a continuación? Los ejemplos serían excelentes.T-SQL JOIN contra una Expresión de tabla común (CTE)

Por ejemplo:

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] 

Aquí está mi consulta completa:

;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) 

Gracias tanto!

Respuesta

30

Cuando define un CTE lo hace antes del resto de la consulta. Así que no se puede escribir:

LEFT JOIN (
    ;WITH CTE 
    ... 
) 

Como rápida a un lado, la razón personas ponen ; frente a WITH se debe a que todas las declaraciones anteriores necesitan ser terminados. Si los desarrolladores podían conseguir en el hábito de poner fin a todas las sentencias SQL con ; entonces no sería necesario, pero estoy divagando ...

Puede escribir varias CTE, así:

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

Y siempre que un CTE se defina antes que otros, se lo puede consultar dentro de los CTE siguientes. – Bora

1

Puede tener múltiples CTE, creo; solo tienes que ponerlos a los dos en la parte superior.

Ver here:

Puede, sin embargo, definir múltiples CTE después de la palabra clave WITH separando cada CTE con una coma.

2

Si usted tiene múltiples CTE, tienen que estar al principio de su declaración (separada por comas, y sólo una ;WITH para iniciar la lista de CTE):

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

y entonces usted puede use ambos (o incluso más de dos) en su declaración SELECT.

3

Múltiple CTE debe declararse primero. Ejemplo:

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] 
Cuestiones relacionadas