2016-01-24 32 views
0

我有一個CLR聚合級聯功能,類似於https://gist.github.com/FilipDeVos/5b7b4addea1812067b09數串的不同序列。當行數很少時,連接字符串的順序跟隨輸入數據集。當行數較大(幾十個甚至更多)時,序列似乎不確定。有一個在執行計劃的不同,但我不認爲熟悉的優化和什麼提示申請(我試過MAXDOP 1,沒有成功)。從不同的測試中得到類似的結果,下面的例子似乎是計劃中的差異 - 單獨排序,然後是合併連接。它打翻了這裏的行數爲60Sql Server的骨料串連CLR返回基於的記錄

取得了預期的效果: enter image description here

取得了意想不到的結果: enter image description here

下面是與演示問題在AdventureWorks2014示例數據庫中查詢上面的clr(重命名爲TestConcatenate)。預期的結果是一個數據集,每個訂單都有一個行,並且一個列中包含按數量順序排列的該訂單的產品分隔列表。

;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的CTE被限制爲53598,53595,順序正確的是(頂部設置),當它在main中的約束選擇53598,53595,該序列不是(鈕一組)。 enter image description here

那麼,什麼是我的問題嗎?我如何構建查詢,並使用提示或其他更改來返回與行數無關的一致(和正確)排序的連續值。

回答

2

就像一個正常的查詢,如果沒有order by子句,返回順序是不能保證。如果我沒有記錯,SQL 92規範允許通過over子句將order by子句傳遞給聚合,SQL Server不實現它。因此,有沒有辦法保證你的CLR函數排序(除非你通過收集在AccumulateMerge方法,一切都變成某種集合,然後返回之前排序在Terminate方法列表實現它自己。但你會付出在內存授權方面的成本,因爲現在需要序列化集合

至於爲什麼你看到基於結果集大小的不同行爲,我注意到在這兩者之間使用了不同的連接運算符。循環聯接和合並聯接通過兩套正在走不同的加入等等,可能佔你所看到的差異。

0

雖然此答案沒有解決方案,但Ben和Orlando提供的附加信息(謝謝!)提供了我需要繼續前進的內容。我會採取奧蘭多指出的方法,這也是我的計劃B,即在clr中排序。