2012-03-30 2 views
2

이 질문이 전에 묻혔는지 모르겠습니다. 하지만 varchars 연결할 때 문제가 있습니다.varchar를 연결할 때 정렬합니다. 예상대로 작동하지 않습니다.

설명해 드리죠 :

을 나는이 테이블이 :

CREATE TABLE Table1 
(
    [Field] [varchar](10) NOT NULL 
) 
INSERT INTO Table1 
VALUES('1'),('2'),('3'),('4'),('5'),('TITLE') 

를 내가 이렇게 될 출력을 좋아한다 :

'[TITLE],[1],[2],[3],[4],[5]' 

내가 순서로 '제목'을 원하는 first 1,2,3,4,5

따라서이 쿼리는 정렬 된 결과를 반환합니다.

DECLARE @cols VARCHAR(MAX) 
SELECT @cols = COALESCE(@cols + ','+QUOTENAME([Field]), 
        QUOTENAME([Field])) 
FROM 
    Table1 
ORDER BY 
    LEN([Field]) DESC, 
    [Field] ASC 

그러나이 반환 : 난 내가 보통이 같은 VARCHAR CONCAT 더 후 번호 'TITLE'다음

SELECT 
    * 
FROM 
    Table1 
ORDER BY 
    LEN([Field]) DESC, 
    [Field] ASC 

의 길이가없는

'[5]' 

을 어느 I 찾기가 정말 이상합니다. 누군가 이유를 설명해 주시겠습니까?

나는 varchar를 연결하는 다른 해결책이 있다는 것을 알고있다. 이처럼 :

DECLARE @cols VARCHAR(MAX) 
SELECT @cols=STUFF 
(
    (
     SELECT 
      ',' +QUOTENAME([Field]) 
     FROM 
      Table1 
     ORDER BY 
      LEN([Field]) DESC, 
      [Field] ASC 
     FOR XML PATH('') 
    ) 
,1,1,'') 

이이처럼 내 예상 된 결과를 반환합니다

'[TITLE],[1],[2],[3],[4],[5]' 

편집 @cols이 될 어차피 시작에서 널

제안 것이다. 내가 order by을 제거하면된다. 이처럼 :

DECLARE @cols VARCHAR(MAX) 
SELECT @cols = COALESCE(@cols + ','+QUOTENAME([Field]), 
        QUOTENAME([Field])) 
FROM 
    Table1 

내 결과는 다음과 같이 될 것입니다 :

'[1],[2],[3],[4],[5],[TITLE]' 

EDIT1

이 작동하지 않습니다 :

DECLARE @cols VARCHAR(MAX) 
SELECT @cols = COALESCE(@cols + ','+QUOTENAME([Field]), 
        QUOTENAME([Field])) 
FROM(
    SELECT [Field] 
    FROM 
     Table1 
    ORDER BY 
     LEN([Field]) DESC, 
     [Field] ASC 
) AS t 

을 그것이 예외 메시지를 줄 것이기 때문에 좋아요 :

메시지 1033, 수준 15, 상태 1, 줄 17 ORDER BY 절, TOP하지 않는 한 또는 FOR XML을도 지정되어 뷰, 인라인 함수, 파생 테이블, 하위 쿼리 및 공통 테이블 표현에 유효하지 않습니다.

EDIT2

내가 기대처럼

.이 같은 예외가 발생합니다이 Becuase

SELECT @cols, @cols = COALESCE(@cols + ','+QUOTENAME([Field]), 
        QUOTENAME([Field])) 
FROM 
    Table1 
ORDER BY 
    LEN([Field]) DESC, 
    [Field] ASC 

: 나는이 작업을 수행 할 수 없습니다

변수 필수로 값을 할당 메시지 141, 수준 15, 상태 1, 9 호선하는 SELECT 문을 데이터 검색 조작과 결합해서는 안됩니다.

+0

이 시나리오에 대한 추론을 설명 할 수 있습니까? 일반적으로 텍스트 필드에 숫자를 저장하면 잘못 처리됩니다. 또한 테이블이 100.000 행으로 커지지 않을 것이라는 점을 확실히해야합니다. – SWeko

+0

저는 이것을 동적 인 피벗 (Pivot)으로 만들고 싶습니다. 테이블은 사용할 수 없음을 나타내는 플래그를 제외하고는 정적입니다. 마녀 예를 들어 본 적이 없습니다.이 테이블은 내가 바꿀 수없는 레거시 시스템의 일부입니다. 그것은 고객이 요구하는 보고서 용입니다. – Arion

+0

두 번째 솔루션을 사용할 수없는 이유는 무엇입니까? 의도 한대로 작동합니다. – SWeko

답변

2

와 끝까지

는 ANSI SQL-92 사양 기사 PRB: Execution Plan and Results of Aggregate Concatenation Queries Depend Upon Expression Location BY 절 주문에 의해 참조되는 열이 SELECT 목록에 열 에 의해 정의 된 결과 집합을 일치해야합니다. 표현식이 ORDER BY 절의 멤버에 적용되면 결과 열은 SELECT 목록에 표시되지 않으므로 정의되지 않은 동작이 발생합니다.

order by 절에서 표현식을 사용할 때 다른 실행 계획을 얻습니다.

enter image description here

정렬은 이전에 계산 스칼라 대신 이후에 적용됩니다.

문자열을 주문과 연결하는 안전한 방법은 for xml입니다.

+0

고맙습니다. 이것이 받아들이는 대답입니다. – Arion

3

확실하지 않지만 대답은 쿼리의 실행 순서에 있다고 생각합니다. 기껏 홀수 인 수익률 6

DECLARE @x INT 
SET @x = 0 
SELECT @x [email protected] + 1 
FROM 
    Table1 
ORDER BY 
    LEN(Field) DESC, Field ASC 
SELECT @x 

과 1을 반환, 아직

DECLARE @x INT 
SET @x = 0 
SELECT @x [email protected] + 1 
FROM 
    Table1 
SELECT @x 

: 나는 다음과 같은 코드를 시도했습니다.

Table Scan -> Compute Scalar -> Sort -> Select 

그래서 내 추측이 결과가 먼저 분류, 계산이다, 당신은 몇 가지로 끝날 :

그러나, 첫 번째 쿼리의 실행 계획에서 이벤트의 순서는 것을 알 수있다 중간 값.

IMHO, 이것은 SQL Server 실행 엔진의 남용이며 기본적으로 정의되지 않은 동작입니다. 이 SQL 서버에서 작동하도록 관리 할지라도 서비스 팩으로 문제가 발생하는지 알 수 없습니다. 내가 설명했던 두 번째 해결책은 간단하고 유지하기 쉽습니다. EDIT1 소개


: SELECT TOP 100 PERCENT 지정은 "뷰에서 어떤 주문"을 담당 오류는, 그러나, SQL 서버는 약간의 마법을 수행, 당신은 여전히 ​​당신이 한 번 봐 가질 수 [1],[2],[3],[4],[5],[TITLE]

+0

이제 이건 아마 어리석은 질문입니다. 그러나 순서를 변경하여 '정렬'전에 먼저 '계산 스칼라'우선 순위를 변경할 수 있습니까? 그리고 대체 솔루션이 아마도 더 낫다고 나는 동의한다. 또한 유지 측면에서. – Arion

+0

한 마디로, 아니요. 테이블 힌트를 사용하여 일부 실행 계획을 수행 할 수 있지만 일반적으로 실행 계획 경로는 내부 SQL 서버 작업입니다. – SWeko

관련 문제