T-SQL SELECT TOP возвращает дубликаты - PullRequest
4 голосов
/ 05 октября 2011

Я использую 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 может возвращать записи в любом порядке, но не понимаю, почему количество возвращаемых записей должно меняться.

Представление использует перекрестное применение, что может как-то повлиять на набор результатов?

РЕДАКТИРОВАТЬ: просмотр определения по запросу

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 ]

3 голосов
/ 05 октября 2011

Я бы предположил, что происходит некий детерминизм, который означает, что разные методы доступа могут возвращать разные результаты.

Глядя на определение вида, единственное место, которое может появиться, было бы, если бы vwEntity_Address имел несколько дубликатов для Entity_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
2 голосов
/ 05 октября 2011

Мне было интересно, включает ли ваша точка зрения функцию, пока я не дошел до конца, где вы говорите, что используете перекрестное применение.Я хотел бы предположить, что это ваша проблема, если вы заинтересованы в деталях, взгляните на различные планы запросов.

РЕДАКТИРОВАТЬ: расширение ответа Т.е. ваша функция недетерминирована и может либо возвратить более одной строкина вход или вернуть ту же строку для другого входа.В сочетании это означает, что вы получите именно то, что видите: дублирующиеся строки под некоторыми ограничениями.Добавление отдельного к вашему представлению является дорогостоящим способом решения вашей проблемы. Лучшим способом было бы изменить вашу функцию так, чтобы для любого ввода был только один выход строки, а для вывода строки только один вход будет производить эту строку.

РЕДАКТИРОВАТЬ: я не видел, что вы сейчас включаете ваше определение представления.Ваша проблема, безусловно, заключается в перекрестном применении, в частности, вы выполняете сортировку внутри перекрестного применения по значениям ОТ ВНЕШНЯГО перекрестного применения, в результате чего верхняя точка 1 фактически является случайной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...