针对公用表表达式 (CTE) 的 T-SQL JOIN
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8403339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
T-SQL JOIN against a Common Table Expression (CTE)
提问by Jared
Is it possible to perform a JOIN sub query against a Common Table Expression? If not, then can someone let me know how to perform what I am trying to do below? Examples would be excellent.
是否可以针对公共表表达式执行 JOIN 子查询?如果没有,那么有人可以让我知道如何执行我在下面尝试执行的操作吗?例子会很好。
For example:
例如:
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]
Here is my full query:
这是我的完整查询:
;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)
Thanks so much!
非常感谢!
回答by Yuck
When you define a CTE you're doing so before any of the rest of the query. So you can't write:
当您定义 CTE 时,您是在查询的任何其余部分之前这样做。所以你不能写:
LEFT JOIN (
;WITH CTE
...
)
As a quick aside, the reasonpeople put ;
in front of WITH
is because all previous statements need to be terminated. If developers could get in the habit of terminating all SQL statements with ;
then it wouldn't be necessary, but I digress...
顺便说一句,人们放在前面的原因是因为所有先前的语句都需要终止。如果开发人员可以养成终止所有 SQL 语句的习惯,那么就没有必要了,但我离题了……;
WITH
;
You can write multiple CTEs like so:
您可以像这样编写多个 CTE:
WITH SomeCTE AS (
SELECT ...
FROM ...
), AnotherCTE AS (
SELECT ...
FROM ...
)
SELECT *
FROM SomeCTE LEFT JOIN
AnotherCTE ON ...
;
回答by marc_s
If you have multiple CTE's, they need to be at the beginning of your statement (comma-separated, and only one ;WITH
to start the list of CTE's):
如果您有多个 CTE,则它们需要位于语句的开头(逗号分隔,并且只有一个;WITH
用于开始 CTE 列表):
;WITH CTE AS (......),
[UserDefined] AS (.......)
SELECT.....
and then you can use both (or even more than two) in your SELECT
statement.
然后你可以在你的SELECT
语句中同时使用这两个(甚至两个以上)。
回答by James Hill
Multiple CTE need to be declared first. Example:
需要先声明多个 CTE。例子:
WITH CTE_1 AS
(
....
),
CTE_2 AS
(
...
)
SELECT *
FROM FOO
LEFT JOIN CTE_1
LEFT JOIN CTE_2
回答by MatBailie
;
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]