Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server Sql Server聚合连接CLR根据记录数返回不同的字符串序列_Sql Server_Clr - Fatal编程技术网

Sql server Sql Server聚合连接CLR根据记录数返回不同的字符串序列

Sql server Sql Server聚合连接CLR根据记录数返回不同的字符串序列,sql-server,clr,Sql Server,Clr,我有一个clr聚合连接函数,类似于。当行数较少时,串联字符串的序列跟随输入数据集。当行数较大(几十行或更多行)时,序列似乎不确定。执行计划有所不同,但我不太熟悉优化器以及应用什么提示(我尝试了MAXDOP 1,但没有成功)。从一个与下面的示例不同的测试中得到了类似的结果,这似乎是计划中的不同之处——单独的排序,然后是合并联接。它翻到这里的排数是60 取得了预期成果: 产生了意想不到的结果: 以下是使用上述clr(重命名为TestConcatenate)演示AdventureWorks2014

我有一个clr聚合连接函数,类似于。当行数较少时,串联字符串的序列跟随输入数据集。当行数较大(几十行或更多行)时,序列似乎不确定。执行计划有所不同,但我不太熟悉优化器以及应用什么提示(我尝试了MAXDOP 1,但没有成功)。从一个与下面的示例不同的测试中得到了类似的结果,这似乎是计划中的不同之处——单独的排序,然后是合并联接。它翻到这里的排数是60

取得了预期成果:

产生了意想不到的结果:

以下是使用上述clr(重命名为TestConcatenate)演示AdventureWorks2014示例数据库中问题的查询。预期结果是一个数据集,其中每个订单有一行,该列按数量顺序为该订单的产品列表设置了分隔符

 ;with cte_ordered_steps AS (
  SELECT top 100000 sd.SalesOrderID, SalesOrderDetailID, OrderQty
  FROM [Sales].[SalesOrderDetail] sd
  --WHERE sd.SalesOrderID IN (53598, 53595)
  ORDER BY sd.SalesOrderID, OrderQty
  )

 select
  sd.SalesOrderID,
  dbo.TestConcatenate(' QTY: ' + CAST(sd.OrderQty AS VARCHAR(9)) + ': ' + IsNull(p.Name, '')) 
 FROM [Sales].[SalesOrderDetail] sd
 JOIN [Production].[Product] p ON p.ProductID = sd.ProductID
 JOIN cte_ordered_steps r ON r.SalesOrderID = sd.SalesOrderID AND r.SalesOrderDetailID = sd.SalesOrderDetailID
 where sd.SalesOrderID IN (53598, 53595)
 GROUP BY sd.SalesOrderID
当SalesOrderID在53598、53595的cte中受约束时,序列是正确的(顶部集合);当SalesOrderID在53598、53595的主选择中受约束时,序列不是正确的(底部集合)。


那么我的问题是什么?如何使用提示或其他更改构建查询,以返回与行数无关的一致(且正确)序列连接值

与普通查询一样,如果没有ORDERBY子句,则不能保证返回顺序。如果我没记错的话,SQL92规范允许通过over子句将ORDERBY子句传递到聚合中,SQLServer没有实现它。因此,无法保证CLR函数中的顺序(除非您自己通过收集
Accumulate
Merge
方法中的所有内容来实现它,然后在返回之前在
Terminate
方法中对列表进行排序。但是您将支付内存授予方面的成本,因为现在需要序列化集合


至于为什么会根据结果集的大小看到不同的行为,我注意到在这两个结果集之间使用了不同的连接运算符。循环连接和合并连接遍历两个不同的连接集,因此这可能会解释您看到的差异。

就像普通查询一样,如果没有order by子句,不保证返回顺序。如果我没记错的话,SQL 92规范允许通过over子句将order by子句传递到聚合中,SQL Server没有实现它。因此无法保证CLR函数中的顺序(除非您自己通过收集
Accumulate
Merge
方法中的所有内容来实现它,然后在返回之前在
Terminate
方法中对列表进行排序。但是您将支付内存授予方面的成本,因为现在需要序列化集合


至于为什么会根据结果集的大小看到不同的行为,我注意到在这两个结果集之间使用了不同的连接运算符。循环连接和合并连接遍历两个不同的连接集,因此这可能会解释您看到的差异。

为什么不尝试聚合dbo.GROUP_CONCAT_S available at.S用于排序输出。它完全符合您的要求。

为什么不尝试在上提供的聚合dbo.GROUP\u CONCAT\u S.S用于排序输出。它完全符合您的要求。

虽然此答案没有解决方案,但Ben和Orlando提供的附加信息(谢谢!)我将采用Orlando指出的方法,这也是我的计划B,即在clr中进行排序。

虽然这个答案没有解决方案,但Ben和Orlando提供的附加信息(谢谢!)我将采用奥兰多指出的方法,这也是我的B计划,即在clr中排序