Stored proc gives different result set on different server

时间:2018-06-18 11:38:06

标签: sql sql-server tsql

I have put together a stored procedure on my dev machine, which runs SQL Server 10.50.6220 (Express). It works correctly and returns the expected (and consistent) results.

I have then done a full backup and restored to a test machine running SQL Server 10.50.6000.34. The stored proc on the new server now returns incorrect results, whats more, the results it returns are different each time it is run.

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

Each row of underlying data contains a staff member, the station they were working at and their start & finish times. The purpose of the stored proc is to return a list of stations, along with the number of mins that each quantity of workers were at that station, as below:

enter image description here

My question is, what could be causing the incorrect and inconsistent results on the test server? And what can I do to fix it?

I have read this, possibly related, question:

Stored proc gives different result set than tsql, only on some servers

and have tried creating local variables for the parameters but it does not seem to have any effect.

2 个答案:

答案 0 :(得分:2)

  

可能导致结果不一致的原因

  1. 非确定性排序

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

    通过ORDER BY(SELECT 1),您告诉优化器,您不关心行的编号顺序。我没有分析整个查询,但情况确实如此吗?

  2. 另一个有强烈气味的位是SELECT TOP 100 PERCENT,内部/子查询中有一些ORDER BY。看起来你认为在内部查询中添加这样的ORDER BY可以保证一些东西。它没有。

  3. 如果您需要按[Time] DESC订购的行号,请将其放入ROW_NUMBER

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

答案 1 :(得分:1)

感谢@Vladimir,我设法调整了存储过程,以便返回正确的结果。正如所建议的那样,我将排序行为移到了ROW_NUMBER函数,而不是ORDER BY子句(尽管它实际上需要是ASC,而不是DESC)。

我会将他的答案标记为正确,但我认为我会在此处发布我的最终代码以确保完整性:

<Window
  ....
  xmlns:viewModels="clr-namespace:MyProject.ViewModels">
<Window.DataContext>
    <viewModels:MyViewModel />
</Window.DataContext>

<Grid>
...
    <TextBlock Text="{Binding myClass.MyProperty}" />
...
</Grid>