2011-10-05 62 views
4

我正在使用SQL Server 2008 R2。T-SQL SELECT TOP返回重複項

我不確定我是否發現了一個奇怪的SQL怪癖,或者(更可能)是我的代碼中的某些內容導致了這種奇怪的行爲,特別是因爲Google什麼也沒有發現。我有一個名爲vwResponsible_Office_Address的視圖。

SELECT * FROM vwResponsible_Office_Address 

..returns 403行

此代碼:

SELECT TOP 1000 * FROM vwResponsible_Office_Address 

..returns 409行,因爲它包括6個重複。

然而這樣的:

SELECT TOP 1000 * FROM vwResponsible_Office_Address 
ORDER BY ID 

再次..returns 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 
+1

您可以發佈您'VIEW'定義是什麼? – a1ex07

+0

請同時包含'vwEntity_Address'視圖的代碼。 – James

+0

如果繞過視圖並運行TSQL direct,您是否會遇到同樣的問題?計數(*)如何? – Paparazzi

回答

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 
+0

您是否認爲使用窗口函數來獲取任意第一個地址使其更具確定性,或者與使用CROSS APPLY –

+0

@ConradFrix相同 - 爲了確定OP,需要通過一個決定因素來決定,例如添加'ORDER BY'列表末尾的'Address_ID.'。 –

+0

hmm well ea。[Address_ID]已經在CROSS APPLY中刪除。 OP會在哪裏添加Address_id? –

2

我在想,如果您的視圖包含一個函數,直到我到了年底,你說你使用交叉應用。我會認爲這是您的問題,如果您對細節感興趣,請查看各種查詢計劃。

編輯:擴大回答 即使您的函數是非確定性的,並且可以爲每個輸入返回多個行或爲不同的輸入返回相同的行。綜合起來,這意味着你會得到你所看到的完全一樣的東西:在某些環境下重複行。爲你的視圖添加一個獨特的代價是解決你的問題的代價昂貴的方法,更好的方法是改變你的函數,以便任何輸入只有一個行輸出,而對於一個行輸出只有一個輸入將產生該行。

編輯:我沒有看到你現在包括你的視圖定義。 你的問題是絕對的交叉應用,特別是你正在交叉內部排序應用來自交叉應用的外部值,使得頂部1有效地隨機。