2013-06-18 2 views
0

하위 쿼리와 함께 교차 적용되는 다음 sql 쿼리가 있습니다.Sql 쿼리 (CROSS가 적용됨) throwing error

SELECT 
    pm.[FileName] 
    ,REPLACE([Message], 'Upload End. Total Row:', '') cnt_char 
    ,CAST(REPLACE([Message], 'Upload End. Total Row:', '') AS INT) AS row_count 
FROM 
    dbo.ProductMaster pm 
CROSS APPLY 
    (SELECT TOP 30 * 
    FROM dbo.ActivityLog lo 
    WHERE [Message] like 'Upload End%' 
     AND lo.[FileName] = pm.[FileName] 
    ORDER BY ActivityDate DESC) AS s 

그것은 잘 실행하지만 난에 두 번째 표현식 (,REPLACE([Message], 'Upload End. Total Row:', '') cnt_char)를 제거하는 경우의 I는 다음과 같은 오류

에게 메시지 245, 수준 16, 상태 1, 줄 1
얻을 변환이 실패 선택 varchar 값 'Upload Start'를 데이터 유형 int로 변환 할 때.

하위 쿼리의 where 절은 Message가 "Upload Start"인 모든 행을 특별히 제외해야하지만 왜이 오류가 발생합니까? CROSS APPLY을 올바르게 사용하지 않습니까?

답변

1

SQL이 설명하는 언어가 아닌 절차 적 언어입니다. cross apply의 메소드는 결과가 어떻게 생성되는지 논리적으로 설명합니다. 그들은 실행 계획을 지정하지 않습니다. 쿼리 최적화 프로그램은 올바른 결과 집합을 생성하는 쿼리 계획을 자유롭게 선택할 수 있습니다.

두 쿼리에 대한 실행 계획을 확인해야합니다. 내 생각에 그들은 근본적인 방식으로 다르다. 유형 변환을 처리 할 때 을 필터링하기 위해 where 절에 의존하지 말고 변환하십시오. 대신 case을 사용해야합니다. 외부 쿼리는 다음과 같이 표시되어야합니다.

1

SQL Server는 원하는 순서대로 쿼리를 실행할 수 있습니다. 즉, 모든 행을 선택하고 나중에 필터 만 적용 할 수 있습니다. 동일한 결과를 보장하는 방법으로 허용됩니다.

불행히도,이 보증은 연산자를 캐스팅하지 않고 관계형 논리 만 포함합니다.

한 가지 방법은 밖으로 한 번 확인입니다 :

case when Message like 'Upload End.%' then 
    CAST(REPLACE([Message], 'Upload End. Total Row:', '') AS INT) 
else null 
end AS row_count 
+0

귀하의 답변은 동의 한 것과 동일하지만 다른 하나의 설명에 따르면 더 잘 설명됩니다. 나는 널지지했다. 감사. – Satish