簡體   English   中英

存儲的過程在不同的服務器上給出不同的結果集

[英]Stored proc gives different result set on different server

我在運行SQL Server 10.50.6220(Express)的開發機上放了一個存儲過程。 它可以正常工作,並返回預期的(和一致的)結果。

然后,我完成了完整備份,並還原到運行SQL Server 10.50.6000.34的測試計算機上。 現在,新服務器上存儲的proc返回的結果不正確,而且每次運行時返回的結果都不同。

ALTER PROCEDURE [dbo].[Get_Station_Utilisation]
@From       NVARCHAR(50),
@To         NVARCHAR(50)

AS

IF @From='' SET @From = NULL
IF @To='' SET @To = NULL

SELECT T.StationID As [Station ID], dbo.Stations.StationName As [Station Name], T.StaffWorking As [Workers], T.Mins
FROM
    (SELECT StatsID As StationID, [Count] As StaffWorking, SUM(Duration) AS Mins
    FROM
        (SELECT dbo.Active_Clockings.StationID AS StatsID, COUNT(*) AS [Count], DATEDIFF(Minute, Times2.Time, Times1.Time) AS Duration
        FROM            
            (SELECT TOP 100 PERCENT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rownum, [Time]
            FROM            
                (SELECT DISTINCT (dbo.Active_Clockings.StartTime) AS [Time]
                FROM    dbo.Active_Clockings
                UNION
                SELECT DISTINCT (dbo.Active_Clockings.FinishTime) AS [Time]
                FROM    dbo.Active_Clockings) AS AllTimes
                ORDER BY [Time] DESC) AS Times1 JOIN
                    (SELECT TOP 100 PERCENT ROW_NUMBER() OVER (ORDER BY(SELECT 1)) AS rownum, [Time]
                    FROM
                        (SELECT DISTINCT (dbo.Active_Clockings.StartTime) AS [Time]
                        FROM    dbo.Active_Clockings
                        UNION
                        SELECT DISTINCT (dbo.Active_Clockings.FinishTime) AS [Time]
                        FROM    dbo.Active_Clockings) AS AllTimes
                        ORDER BY [Time] DESC) AS Times2 ON Times1.rownum = Times2.rownum + 1 JOIN
                            dbo.Active_Clockings ON Times1.Time > dbo.Active_Clockings.StartTime AND Times2.Time < dbo.Active_Clockings.FinishTime
                            AND (@From IS NULL OR (dbo.Active_Clockings.FinishTime > CAST(@From as date)))
                            AND (@To IS NULL OR dbo.Active_Clockings.FinishTime < DATEADD(Day, 1, CAST(@To as date)))
                        GROUP BY Times1.rownum, Times2.Time, Times1.Time, dbo.Active_Clockings.StationID) AS Totals
                GROUP BY [Count], StatsID
) AS T INNER JOIN 
    dbo.Stations ON T.StationID= dbo.Stations.ID
ORDER BY T.StationID, T.StaffWorking ASC

基礎數據的每一行都包含一個工作人員,他們工作的工作站以及開始和結束時間。 存儲的proc的目的是返回工作站列表,以及每個數量的工人在該工作站的分鍾數,如下所示:

在此處輸入圖片說明

我的問題是,是什么原因導致測試服務器上的結果不正確和不一致? 而我該如何解決呢?

我已經閱讀了這個可能相關的問題:

存儲的proc僅在某些服務器上提供與tsql不同的結果集

並嘗試為參數創建局部變量,但這似乎沒有任何效果。

是什么導致不一致的結果

  1. 非確定性排序

     ROW_NUMBER() OVER (ORDER BY(SELECT 1)) 

    通過ORDER BY(SELECT 1)您在這里告訴優化器,您不在乎行的編號順序。 我沒有分析整個查詢,但確實如此嗎?

  2. 氣味強烈的另一個地方是SELECT TOP 100 PERCENT ,內部/子查詢中有一些ORDER BY 看起來您認為在內部查詢中添加這樣的ORDER BY保證某些事情。 沒有。


如果您需要按[Time] DESC排序的行號,則將其放在ROW_NUMBER

ROW_NUMBER() OVER (ORDER BY [Time] DESC)

感謝@Vladimir,我設法調整了存儲過程,以便它返回正確的結果。 如建議的那樣,我將排序行為移至ROW_NUMBER函數,而不是ORDER BY子句(盡管實際上它需要是ASC,而不是DESC)。

我會將他的回答標記為正確,但以為完整起見,我會在此處發布最終代碼:

ALTER PROCEDURE [dbo].[Get_Station_Utilisation]
@From       NVARCHAR(50),
@To         NVARCHAR(50)

AS

IF @From='' SET @From = NULL
IF @To='' SET @To = NULL


SELECT T.StationID As [Station ID], dbo.Stations.StationName As [Station Name], T.StaffWorking As [Workers], T.Mins
FROM
    (SELECT StatsID As StationID, [Count] As StaffWorking, SUM(Duration) AS Mins
    FROM
        (SELECT dbo.Active_Clockings.StationID AS StatsID, COUNT(*) AS [Count], DATEDIFF(Minute, Times2.Time, Times1.Time) AS Duration
        FROM            
            (SELECT ROW_NUMBER() OVER (ORDER BY [Time] ASC) AS rownum, [Time]
            FROM            
                (SELECT DISTINCT (dbo.Active_Clockings.StartTime) AS [Time]
                FROM    dbo.Active_Clockings
                UNION
                SELECT DISTINCT (dbo.Active_Clockings.FinishTime) AS [Time]
                FROM    dbo.Active_Clockings) AS AllTimes
                ) AS Times1 JOIN
                    (SELECT ROW_NUMBER() OVER (ORDER BY [Time] ASC) AS rownum, [Time]
                    FROM
                        (SELECT DISTINCT (dbo.Active_Clockings.StartTime) AS [Time]
                        FROM    dbo.Active_Clockings
                        UNION
                        SELECT DISTINCT (dbo.Active_Clockings.FinishTime) AS [Time]
                        FROM    dbo.Active_Clockings) AS AllTimes
                        ) AS Times2 ON Times1.rownum = Times2.rownum + 1 JOIN
                            dbo.Active_Clockings ON Times1.Time > dbo.Active_Clockings.StartTime AND Times2.Time < dbo.Active_Clockings.FinishTime
                            AND (@From IS NULL OR (dbo.Active_Clockings.FinishTime > CAST(@From as date)))
                            AND (@To IS NULL OR dbo.Active_Clockings.FinishTime < DATEADD(Day, 1, CAST(@To as date)))
                        GROUP BY Times1.rownum, Times2.Time, Times1.Time, dbo.Active_Clockings.StationID) AS Totals
                GROUP BY [Count], StatsID
) AS T INNER JOIN 
    dbo.Stations ON T.StationID= dbo.Stations.ID
ORDER BY T.StationID, T.StaffWorking ASC

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM