T-SQL SELECT TOP返回重复项

时间:2011-10-05 15:40:19

标签: sql sql-server tsql sql-server-2008 select

我正在使用SQL Server 2008 R2。

我不确定我是否发现了一个奇怪的SQL怪癖,或者(更有可能)我的代码中的某些内容导致了这种奇怪的行为,特别是因为谷歌没有发现任何东西。我有一个名为vwResponsible_Office_Address的视图。

SELECT * FROM vwResponsible_Office_Address

..返回403行

此代码:

SELECT  TOP 1000 *  FROM vwResponsible_Office_Address

..返回409行,因为它包含6个重复项。

但是这个:

SELECT  TOP 1000 *  FROM vwResponsible_Office_Address
ORDER BY ID

..再次返回403行。

我可以发布视图的代码,如果它是相关的,但SELECT TOP是否有意义以这种方式工作?我理解SELECT TOP可以按任何顺序自由返回记录,但不明白为什么返回的记录数量会有所不同。

视图确实使用交叉应用,这可能会影响结果集的某些方式?

编辑:按要求查看定义

CREATE VIEW [dbo].[vwResponsible_Office_Address] 
AS
    SELECT  fp.Entity_ID [Reg_Office_Entity_ID],
            fp.Entity_Name [Reg_Office_Entity_Name],
            addr.Address_ID
    FROM [dbo].[Entity_Relationship] er
    INNER JOIN [dbo].[Entity] fp
        ON er.[Related_Entity_ID] = fp.[Entity_ID]
    INNER JOIN [dbo].[Entity_Address] ea
        ON ea.[Entity_ID] = fp.[Entity_ID]
    CROSS APPLY (
        SELECT TOP 1 Address_ID 
        FROM [dbo].[vwEntity_Address] vea   
        WHERE [vea].[Entity_ID] = fp.Entity_ID  
        ORDER by ea.[Address_Type_ID] ASC, ea.[Address_ID] DESC
    ) addr
    WHERE [Entity_Relationship_Type_ID] = 25 -- fee payment relationship

    UNION

    SELECT  ets.[Entity_ID],
            ets.[Entity_Name],
            addr.[Address_ID]
    FROM  dbo.[vwEntity_Entitlement_Status] ets
    INNER JOIN dbo.[Entity_Address] ea
        ON ea.[Entity_ID] = ets.[Entity_ID]
    CROSS APPLY (
        SELECT TOP 1 [Address_ID]
        FROM  [dbo].[vwEntity_Address] vea
        WHERE vea.[Entity_ID] = ets.[Entity_ID]
        ORDER by ea.[Address_Type_ID] ASC, ea.[Address_ID] DESC
    ) addr
    WHERE ets.[Entitlement_Type_ID] = 40 -- registered office
    AND ets.[Entitlement_Status_ID] = 11 -- active

2 个答案:

答案 0 :(得分:3)

我认为存在一些非确定性,这意味着不同的访问方法可以返回不同的结果。

查看视图定义唯一可能出现的地方vwEntity_AddressEntity_ID的重复项。

这会使top 1 Address_ID在这种情况下返回任意值,这会在删除重复项时影响union操作的结果。

肯定这看起来非常可疑

SELECT TOP 1 [Address_ID]
        FROM  [dbo].[vwEntity_Address] vea
        WHERE vea.[Entity_ID] = ets.[Entity_ID]
        ORDER by ea.[Address_Type_ID] ASC, ea.[Address_ID] DESC

您要按交叉申请中外部查询的值进行排序。这绝对没有任何影响,因为对于特定的CROSS APPLY调用,这些将是常量。

您可以尝试更改为

SELECT TOP 1 [Address_ID]
        FROM  [dbo].[vwEntity_Address] vea
        WHERE vea.[Entity_ID] = ets.[Entity_ID]
        ORDER by vea.[Address_ID] DESC

答案 1 :(得分:2)

我想知道你的观点是否包含一个功能,直到我结束,你说你使用交叉申请。我认为这是你的问题,如果你对细节感兴趣,请看一下各种查询计划。

编辑:扩大答案 即您的函数是非确定性的,可以为每个输入返回多行,也可以为不同的输入返回相同的行。结合起来,这意味着您将获得您所看到的内容:在某些环境下重复行。为您的视图添加一个独特的方法是解决问题的昂贵方法,更好的方法是更改​​您的函数,以便任何输入只有一行输出,而对于行输出,只有一个输入将产生该行。 / p> 编辑:我没有看到您现在包含您的视图定义。 你的问题绝对是交叉应用,特别是你在交叉应用中通过交叉应用的OUTSIDE中的值进行排序,使得前1有效地随机。