Ale*_*rey 2 sql sql-server common-table-expression
我正在尝试找出我们在上一次测试过程中发现的错误.它涉及使用公用表表达式的查询.查询的主题是它模拟"第一个"聚合操作(获取此分组的第一行).
问题是,查询,似乎在某些情况下完全任意选择行-从同一组的多个行得到恢复,一些群体根本得到完全消除.但是,它总是选择正确的行数.
我已经创建了一个最小的例子来发布.有客户端和地址,以及定义它们之间关系的表.这是一个多少我期待在实际查询的简化版,但我相信它应该具有相同的特性,它是用来解释什么,我觉得是走错了一个很好的例子.
CREATE TABLE [Client] (ClientID int, Name varchar(20))
CREATE TABLE [Address] (AddressID int, Street varchar(20))
CREATE TABLE [ClientAddress] (ClientID int, AddressID int)
INSERT [Client] VALUES (1, 'Adam')
INSERT [Client] VALUES (2, 'Brian')
INSERT [Client] VALUES (3, 'Charles')
INSERT [Client] VALUES (4, 'Dean')
INSERT [Client] VALUES (5, 'Edward')
INSERT [Client] VALUES (6, 'Frank')
INSERT [Client] VALUES (7, 'Gene')
INSERT [Client] VALUES (8, 'Harry')
INSERT [Address] VALUES (1, 'Acorn Street')
INSERT [Address] VALUES (2, 'Birch Road')
INSERT [Address] VALUES (3, 'Cork Avenue')
INSERT [Address] VALUES (4, 'Derby Grove')
INSERT [Address] VALUES (5, 'Evergreen Drive')
INSERT [Address] VALUES (6, 'Fern Close')
INSERT [ClientAddress] VALUES (1, 1)
INSERT [ClientAddress] VALUES (1, 3)
INSERT [ClientAddress] VALUES (2, 2)
INSERT [ClientAddress] VALUES (2, 4)
INSERT [ClientAddress] VALUES (2, 6)
INSERT [ClientAddress] VALUES (3, 3)
INSERT [ClientAddress] VALUES (3, 5)
INSERT [ClientAddress] VALUES (3, 1)
INSERT [ClientAddress] VALUES (4, 4)
INSERT [ClientAddress] VALUES (4, 6)
INSERT [ClientAddress] VALUES (5, 1)
INSERT [ClientAddress] VALUES (6, 3)
INSERT [ClientAddress] VALUES (7, 2)
INSERT [ClientAddress] VALUES (8, 4)
INSERT [ClientAddress] VALUES (5, 6)
INSERT [ClientAddress] VALUES (6, 3)
INSERT [ClientAddress] VALUES (7, 5)
INSERT [ClientAddress] VALUES (8, 1)
INSERT [ClientAddress] VALUES (5, 4)
INSERT [ClientAddress] VALUES (6, 6)
;WITH [Stuff] ([ClientID], [Name], [Street], [RowNo]) AS
(
SELECT
[C].[ClientID],
[C].[Name],
[A].[Street],
ROW_NUMBER() OVER (ORDER BY [A].[AddressID]) AS [RowNo]
FROM
[Client] [C] INNER JOIN
[ClientAddress] [CA] ON
[C].[ClientID] = [CA].[ClientID] INNER JOIN
[Address] [A] ON
[CA].[AddressID] = [A].[AddressID]
)
SELECT
[CTE].[ClientID],
[CTE].[Name],
[CTE].[Street],
[CTE].[RowNo]
FROM
[Stuff] [CTE]
WHERE
[CTE].[RowNo] IN (SELECT MIN([CTE2].[RowNo]) FROM [Stuff] [CTE2] GROUP BY [CTE2].[ClientID])
ORDER BY
[CTE].[Name] ASC,
[CTE].[Street] ASC
DROP TABLE [ClientAddress]
DROP TABLE [Address]
DROP TABLE [Client]
Run Code Online (Sandbox Code Playgroud)
该查询旨在获取所有客户端及其第一个地址(ID最低的地址).在我看来它应该工作.
我有一个关于为什么它有时不起作用的理论.CTE之后的陈述是指两个地方的CTE.如果CTE的不确定性,并且它被运行一次以上,热膨胀系数的结果可能是在它引用的两个地方不同.
在我的例子中,CTE的RowNo列BY子句中多次运行时(我们通过地址排序,这将可能导致不同的排序使用与订单ROW_NUMBER(),客户可以在任何顺序取决于如何执行查询).
因为这可能CTE和CTE2可能包含不同的结果?或者CTE只执行一次,我是否需要寻找其他问题?
不保证任何方式.
SQL ServerCTE每次访问时都可以自由评估或缓存结果,具体取决于计划.
您可能想阅读这篇文章:
如果您CTE不确定,则必须将其结果存储在临时表或表变量中,并使用它而不是CTE.
PostgreSQL另一方面,总是CTE只评估一次,缓存他们的结果.