如果数据保持不变,有没有办法为同一个SQL查询获得不同的结果?

时间:2011-08-19 14:25:59

标签: sql tsql sql-server-2008

当我运行它时间歇性地为此查询获得不同的结果集...有时它给出1363,有时1365,有时1366结果。数据不会改变。可能导致这种情况的原因是什么方法可以防止它?查询看起来像这样:

SELECT * 
FROM 
    (
            SELECT  
                        RC.UserGroupId,
                        RC.UserGroup,
                        RC.ClientId AS CLID,                     
                        CASE WHEN T1.MultipleClients = 1 THEN RC.Salutation1 ELSE RC.DisplayName1 END AS szDisplayName,
                        T1.MultipleClients,
                        RC.IsPrimaryRecord,
                        RC.RecordTypeId,
                        RC.ClientTypeId,
                        RC.ClientType,
                        RC.IsDeleted,
                        RC.IsCompany,                                            
                        RC.KnownAs,
                        RC.Salutation1,
                        RC.FirstName, 
                        RC.Surname,                   
                        Relationship, 
                        C.DisplayName Client,
                        RC.DisplayName RelatedClient, 
                        E.Email,                                                            
                        RC.DisplayName  + ' is the ' + R.Relationship + ' of ' + C.DisplayName Description,
                        ROW_NUMBER() OVER (PARTITION BY E.Email ORDER BY Relationship DESC) AS sequence_id


            FROM 
                        SSDS.Client.ClientExtended C 
                                                                              INNER JOIN 
                        SSDS.Client.ClientRelationship R WITH (NOLOCK)ON C.ClientId = R.ClientID 
                                                                              INNER JOIN 
                        SSDS.Client.ClientExtended RC WITH (NOLOCK)ON R.RelatedClientId = RC.ClientId
                                                                              LEFT OUTER JOIN
                        SSDS.Client.Email E WITH (NOLOCK)ON RC.ClientId = E.ClientId                 
                                                                              LEFT OUTER JOIN 
                        SSDS.Client.UserDefinedData UD WITH (NOLOCK)ON C.ClientId = UD.ClientId AND C.UserGroupId = UD.UserGroupId 
                                                                              INNER JOIN                                                                 

                        (
                              SELECT 
                                          E.Email, 
                                          CASE WHEN (COUNT(DISTINCT RC.DisplayName) > 1) THEN 1 ELSE 0 END AS MultipleClients 

                              FROM
                                          SSDS.Client.ClientExtended C 
                                                                                                INNER JOIN 
                                          SSDS.Client.ClientRelationship R WITH (NOLOCK)ON C.ClientId = R.ClientID 
                                                                                                INNER JOIN 
                                          SSDS.Client.ClientExtended RC WITH (NOLOCK)ON R.RelatedClientId = RC.ClientId
                                                                                                LEFT OUTER JOIN
                                          SSDS.Client.Email E WITH (NOLOCK)ON RC.ClientId = E.ClientId                 
                                                                                                LEFT OUTER JOIN 
                                          SSDS.Client.UserDefinedData UD WITH (NOLOCK)ON C.ClientId = UD.ClientId AND C.UserGroupId = UD.UserGroupId

                              WHERE 
                                          Relationship IN ('z-Group Principle', 'z-Group Member ')           
                                          AND E.Email IS NOT NULL

                              GROUP BY E.Email 

                        ) T1 ON E.Email = T1.Email


            WHERE 

                                                Relationship IN ('z-Group Principle', 'z-Group Member ')           
                                                AND E.Email IS NOT NULL                                         
    ) T


WHERE       
            sequence_id = 1
            AND T.UserGroupId IN (Select * from iCentral.dbo.GetSubUserGroups('471b9cbd-2312-4a8a-bb20-35ea53d30340',0))         
            AND T.IsDeleted = 0           
            AND T.RecordTypeId = 1 
            AND T.ClientTypeId IN
            (
                        '1',              --Client
                        '-1652203805'    --NTU                      
            )        

        AND T.CLID NOT IN
          (
            SELECT DISTINCT  
                               UDDF.CLID
            FROM
                   SLacsis_SLM.dbo.T_UserDef UD WITH (NOLOCK) 
                          INNER JOIN
                   SLacsis_SLM.dbo.T_UserDefData UDDF WITH (NOLOCK)
                   ON UD.UserDef_ID = UDDF.UserDef_ID
                          INNER JOIN
                   SLacsis_SLM.dbo.T_Client CLL WITH (NOLOCK)
                   ON CLL.CLID = UDDF.CLID AND CLL.UserGroup_CLID = UD.UserID

            WHERE 
                           UD.UserDef_ID in    
                                    (
                                    'F68F31CE-525B-4455-9D50-6DA77C66FEE5',                                    
                                    'A7CECB03-866C-4F1F-9E1A-CEB09474FE47'  
                                    )

                           AND UDDF.Data = 'NO'
           ) 


ORDER BY T.Surname

修改

我删除了所有NOLOCK(包括视图和UDF中的那些),我仍然遇到同样的问题。我每次为嵌套的select(T)得到相同的结果,如果我将T的结果集放入查询开头的临时表中并连接到临时表而不是嵌套的select,那么最终的结果集是每次运行查询时都一样。

EDIT2:

我在ROW_NUMBER()上做了一些阅读...我正在通过电子邮件进行分区(其中有重复项)和按关系排序(两个关系中只有一个)。这是否会导致查询不确定,是否有办法解决?

EDIT3:

如果有人感兴趣http://www.mediafire.com/?qo5gkh5dftxf0ml,以下是实际的执行计划。是否可以看到它是从执行计划中提交的读取运行的?我使用WinMerge比较了文件,唯一的区别似乎是计数(ActualRows =“”)。

EDIT4:

这有效:

SELECT * FROM 
(
   SELECT *, 
             ROW_NUMBER() OVER (PARTITION BY B.Email ORDER BY Relationship DESC) AS sequence_id
             FROM
            (

                                    SELECT DISTINCT  
                                    RC.UserGroupId,
                                    ...
            ) B...

EDIT5:

当连续两次运行相同的ROW_NUMBER()查询(原始问题中的T,只选择RC.DisplayName和ROW_NUMBER)时,我会为某些人获得不同的排名:

enter image description here

有没有人有一个很好的解释/示例,为什么或如何在包含重复项的结果集中ROW_NUMBER()每次运行时的排名都不同,最终会改变结果的数量?

EDIT6:

好的,我认为这对我来说很有意义。这种情况发生在人们2人拥有相同的电子邮件地址(例如丈夫和妻子)和关系时。我想在这种情况下,他们的ROW_NUMBER()排名是任意的,每次运行都可以改变。

6 个答案:

答案 0 :(得分:10)

你全部使用NOLOCK意味着你正在进行脏读,会看到未提交的数据,将被回滚的数据,瞬态和不一致的数据等

取下这些,再试一次,报告请求

编辑:删除了NOLOCKS的一些选项

  1. 数据真的在变化
  2. 某些参数或过滤器正在更改(例如GETDATE)
  3. 每次在不同核心上运行的浮点数比较 请参阅dba.se https://dba.stackexchange.com/q/4810/630
  4. udfs或视图中的嵌入式NOLOCK(例如iCentral.dbo.GetSubUserGroups)
  5. ...

答案 1 :(得分:4)

正如我昨天在评论中所说,具有重复E.Email, Relationship值的行的行编号将是任意的。

为了使其具有确定性,您需要执行PARTITION BY B.Email ORDER BY Relationship DESC, SomeUniqueColumn。有趣的是,它使用相同的执行计划在运行之间进行更改。我认为这是散列连接的结果。

答案 2 :(得分:4)

我认为你的问题是分区上的第一行不确定。我怀疑电子邮件和关系并不是唯一的。

    ROW_NUMBER() OVER (PARTITION BY E.Email ORDER BY Relationship DESC) AS sequence_id 

稍后你会检查分区的第一行。

    WHERE   T.sequence_id = 1
        AND T.UserGroupId ... 

如果第一行是任意的,那么你将获得任意比较。您需要添加到ORDER BY以包含完整的唯一键。如果没有唯一键,那么你需要制作一个或任意结果。即使在具有聚簇PK的表上,也不能保证选择行顺序,除非整个PK都在sort子句中。

答案 3 :(得分:3)

这可能与订购有关。您有一个sequence_id定义为按关系排序的row_number。你总是通过关系获得合理的顺序,但除此之外你的row_number将是随机的。因此,每次都可以使用sequence_id 1获取不同的行。这反过来会影响你的where子句,你可以获得不同数量的结果。要解决此问题以获得一致的结果,请在row_number的顺序中添加另一个字段。使用主键确保一致的结果。

答案 4 :(得分:2)

最近有一个KB解决了ROW_NUMBER()的问题...有关详细信息,请参阅FIX: You receive an incorrect result when you run a query that uses the row_number function in SQL Server 2008

然而,这个KB表明在调用并行执行时会出现问题,并且查看执行计划时我看不到这种情况。但是MS在某种情况下发现问题的事实让我成为了一个问题。有点小心 - 也就是说,对于一个足够复杂的查询会出现同样的问题(并且你的执行计划确实看起来足够大)。

因此,可能需要检查SQL Server 2008的补丁级别。

答案 5 :(得分:0)

U必须只使用

Order by

没有分区。

ROW_NUMBER() OVER (ORDER BY Relationship DESC) AS sequence_id