我正在尝试找出我们在最后一次测试迭代中发现的错误。它涉及一个使用公用表表达式的查询。该查询的主要主题是它模拟“第一”聚合操作(为此分组获取第一行)。
问题在于查询在某些情况下似乎完全选择了任意行-从同一组返回多行,而某些组则完全被淘汰。但是,它 总是 选择正确的行数。
我创建了一个最小的示例来发布到这里。有客户和地址,以及一个定义它们之间关系的表。这是一个 多少 我期待在实际查询的简化版,但我相信它应该具有相同的特性,它是用来解释什么,我觉得是走错了一个很好的例子。
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]
该查询旨在获取所有客户端及其第一个地址(ID最低的地址)。在我看来,这应该可以工作。
我有一个关于为什么有时不起作用的理论。CTE后面的声明在两个地方提到了CTE。如果CTE是不确定的,并且运行了不止一次,则CTE的结果在所引用的两个地方可能会有所不同。
在我的示例中,CTE的RowNo列使用ROW_NUMBER()和order by子句,当多次运行时,该子句可能会导致不同的排序(我们按地址排序,根据查询的执行方式,客户端可以采用任何顺序)。
因此,CTE和CTE2可能包含不同的结果吗?还是CTE仅执行一次,我是否需要在其他地方查找该问题?
不能以任何方式保证。
SQL Server``CTE每次访问时都可以自由评估或缓存结果,具体取决于计划。
SQL Server``CTE
您可能需要阅读这篇文章:
如果CTE不确定,则必须将其结果存储在临时表或表变量中,并使用它代替CTE。
CTE
PostgreSQL另一方面,总是CTE只对s计算一次,将其结果缓存。
PostgreSQL