2011-10-05 4 views
4

SQL Server 2008 R2를 사용하고 있습니다.T-SQL SELECT TOP 중복을 반환합니다.

이상한 SQL 버크가 발견되었거나 내 코드에서 뭔가 이상한 행동을 일으키는 지 확실하지 않습니다. 특히 Google에서 아무 것도 나타나지 않았기 때문에 더욱 그렇습니다. vwResponsible_Office_Address라는보기가 있습니다. 이 6 개 중복을 포함하기 때문에,

SELECT TOP 1000 * FROM vwResponsible_Office_Address 

..returns 409 행 :

SELECT * FROM vwResponsible_Office_Address 

403 행

이 코드를

..returns.

그러나 본 :

SELECT TOP 1000 * FROM vwResponsible_Office_Address 
ORDER BY ID 

다시 403 행 ..returns.

뷰와 관련된 코드를 게시 할 수 있지만 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

로 변경하려고 할 수 있습니까? – a1ex07

+0

'vwEntity_Address' 뷰에 대한 코드도 포함시켜주십시오. – James

+0

보기를 건너 뛰고 해당 TSQL을 직접 실행하면 동일한 이형성을 갖게됩니까? 카운트 (*)는 어떨까요? – Paparazzi

답변

3

나는 어떤 결정론이 존재하지 않는다고 가정 할 것이다. 이것은 다른 접근 방법이 다른 결과를 반환 할 수 있다는 것을 의미한다.

보기 정의를 보면 에 대해 vwEntity_Address에 몇 가지 중복 항목이있을 가능성이 높습니다.

이렇게하면 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 호출에 대해 일정하므로이 기능은 전혀 영향을주지 않습니다.

당신은 당신이 당신의`VIEW` 정의를 게시 할 수

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

Window 함수를 사용하여 임의의 첫 번째 주소를 얻으면 더 결정적이되거나 CROSS APPLY를 사용하는 것과 같을 것이라고 생각하십니까? –

+0

@ConradFrix - 결정적으로 만들기 위해 OP는 타이 브레이커에 의해 'Address_ID.'를'ORDER BY'리스트의 끝에 추가하십시오. –

+0

음, 음. [Address_ID] CROSS의 DESC가 이미 적용되었습니다. OP가 Address_id를 추가 할 곳은? –

2

으로 나는 궁금했다. 세부 사항에 관심이 있다면 다양한 쿼리 계획을 살펴 보겠습니다.

편집 : 응답 확장 즉. 함수는 비 결정적이며 입력마다 둘 이상의 행을 반환하거나 다른 입력에 대해 동일한 행을 반환 할 수 있습니다. 이렇게하면 병사가 볼 수있는 것을 정확히 얻을 수 있습니다. 보기에 별개의 기능을 추가하면 값 비싼 방법으로 문제를 해결할 수 있습니다. 더 나은 방법은 함수를 변경하여 모든 입력에 행 출력이 하나만 있고 행 출력의 경우 한 행의 입력 만 해당 행을 생성하는 것입니다.

편집 : 현재보기 정의가 포함되어 있지 않습니다. 문제는 확실히 교차 적용입니다. 특히 십자가 내에서 정렬하는 경우 교차 적용의 외부에서 값을 적용하여 맨 위 1을 효과적으로 무작위로 만듭니다.