1,2,3,6,10,10A, 10B, 11 순서로 다음 문자열을 정렬하는 데이터 정렬이 있습니까?


12

가변 길이의 정수를 포함하는 VARCHAR 열이있는 데이터베이스가 있습니다. 10을 1이 아닌 9 뒤에, 70A를 70 뒤에 오도록 정렬하고 싶습니다 . WHERE 절의 PATINDEX () , CTE 및 CASE 문 으로이 작업을 수행 할 수있었습니다 .

그러나 이것이 불필요 한 데이터 정렬이 있는지 궁금합니다.


다음은 Microsoft가 Connect에서 UserVoice로 마이그레이션했지만 아직 URI를 전달하지 않았 음을 제안하는 새로운 링크입니다 . 조합 옵션으로 "자연 정렬"/ DIGITSASNUMBERS 지원
Solomon Rutzky

2
Microsoft는 충분한 투표를 받으면 SQL Server의 기본 제공 기능으로이 기능을 구현할 것이라고 말했습니다. 여기로 가서 투표 버튼을 클릭하십시오 .
피터 Aylett

답변:


8

데이터 정렬은 코드 페이지, 악센트, 대소 문자, 너비, 가나에 따라 알파벳순으로 정렬됩니다. 숫자 문자 (0-9)에는 속성이 없습니다.

따라서 9항상 모든 종류의 후 10B입니다 .

다음과 같이 언급 하거나 정렬 하면 분할해야합니다 .

ORDER BY
    RIGHT('                              ' + MyColumn, 30)

오른쪽의 길이는 사용 가능한 공간 수를 결정합니다.

물론 가능합니다 :

  • 이 열을 불필요하게 (더 빨리) 만들려면 열을 결합하고 계산 열을 결합하십시오
  • 선행 0을 고집
  • char (위의 내 오른쪽의 저장된 버전)에서 정당화

후자의 두 가지 제안은 위의 오른쪽과 같으며 약간 다릅니다. 빠른 정렬 (필요한 대량 처리 필요 없음)이지만 더 많은 스토리지 필요


어떻게 작동하는지 모르겠습니다. 그것은 2, 2a, 3 등을 위해 휴식을 취합니다.
Mladen Prajdic

@Mladen Prajdic : 맞습니다. 죄송합니다. 알파벳 순으로 잊어 버린
gbn

"에 관한 그래서 9후에 항상 10B어떤 종류의. "는 SQL Server의 방법은 핸들 "DigitsAsNumbers"에 기본 정렬 옵션은 정렬 옵션으로 노출되지 않았기 때문에 단지이다. 그러나 ;-). 이 기능은 Windows 7부터 Windows 탐색기부터 가장 많이 사용되었으며, 특히 파일 탐색기에서 사용할 수있게되었습니다. 그리고 충분한 사람들이 아이디어를지지한다면 언젠가는 SQL Server에 노출 될 수 있습니다. 다음 Connect 제안을 제출하여 볼 롤링을 얻으려고했습니다 . Collation 옵션으로 "natural sorting"/ DIGITSASNUMBERS를 지원 하십시오 .
Solomon Rutzky

8

계산 열 을 설정 한 다음 그에 따라 정렬합니다. 같은 것

CAST( 
     CASE WHEN IS_NUMERIC(left(OtherColumn, 2) = 1) then 
         left(OtherColumn,2) 
     else 
         left(otherColumn, 1)  
AS INT)

그런 다음 열을 색인화 할 수 있으므로이 열을 사용하여 정렬하십시오.


비슷한 문제에 대해 아는 것이 정말 유용합니다. 그러나이 경우 스키마를 변경할 수 없습니다.
저스틴 친애하는

스키마에 추가 할 수 있습니까? 계산 열을 제한하면 항상 뷰를 만들 수 있습니다. 비록 계산 열처럼 최적화 할 수는 없지만.
Aaron Bertrand

인덱싱 된 뷰를 수행하고 Enterprise Edition이있는 경우 쿼리는 수행하려는 작업을 파악할 수있는 경우 인덱싱 된 뷰를 자동으로 사용합니다. 표준형의 경우 WITH (NOEXPAND)를 사용하여 인덱싱 된 뷰를 사용하도록해야합니다. 그 시점에서 당신은 순서대로 사례 진술을해야하지만 그것이 효과가 있어야한다고 생각합니다.
mrdenny

계산 열을 만들 필요가 없습니다. ORDER BY 절에서 해당 표현식을 직접 사용할 수 있습니다.
a_horse_with_no_name

인덱스 또는 테이블 스캔을 보장하려면 가능합니다. 값을 인덱싱하려면 계산 열 또는 인덱싱 된 뷰가 필요합니다.
mrdenny

5

@gbn이 말하는 것을 입증하는 고통스러운 방법을 원한다면 (기본적으로 데이터 정렬에 부분 문자열을 다르게 주문할 수는 없음) 원하는 순서에 대한 계수가있는 빠른 #temp 테이블을 만들 수 있는지 확인하십시오. 데이터 정렬로 정렬하면 동일한 순서가 반환됩니다.

CREATE TABLE #foo(id INT, n NVARCHAR(10));

CREATE TABLE #bar(collation SYSNAME);

SET NOCOUNT ON;

INSERT #foo SELECT 1,'1'
UNION SELECT 2,'2'
UNION SELECT 3,'3'
UNION SELECT 4,'6'
UNION SELECT 5,'10'
UNION SELECT 6,'10A'
UNION SELECT 7,'10B'
UNION SELECT 8,'11';

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'
    WITH x AS 
    (
        SELECT n, rn = ROW_NUMBER() OVER 
        (ORDER BY n COLLATE ' + name + ') FROM #foo
    ) 
    INSERT #bar 
    SELECT TOP (1) ''' + name + ''' FROM x
    WHERE NOT EXISTS
    (
        SELECT COUNT(*) FROM #foo AS f
        WHERE f.id = x.rn
        AND f.n <> x.n
    );' FROM sys.fn_helpcollations();

EXEC sp_executesql @sql;

SELECT collation FROM #bar;

GO
DROP TABLE #foo, #bar;

이것은 약 10 초 만에 실행되며 0 행을 생성합니다. 즉, SQL Server에서 사용할 수있는 데이터 정렬이 없습니다 (최소한 2008 R2, Denali를 시도하지 않은 경우) 예상대로 정렬됩니다. 정렬을 정의하는 다른 방법이 필요합니다.


2

문자열에서 숫자를 실제 숫자로 정렬하는 현명하고 효율적인 방법을 원하십니까? Microsoft Connect 제안에 대한 투표를 고려하십시오 . 데이터 정렬 옵션으로 "자연 정렬"/ DIGITSASNUMBERS 지원


이 질문은 SQL Server에만 해당되는 것이지만이 답변은 아닙니다. 정보에 대한 인식을 높이고 다른 답변에 반대하지 않도록이 정보를 게시해야한다고 생각했습니다.

그러나 SQL Server 외부에서는 특정 환경에서 이러한 유형의 정렬을 수행 할 수 있습니다. 그것은 적어도 유니 코드 문서에 명시된 것입니다. 에서 유니 코드 LOCALE 데이터 마크 업 언어 (LDML) PART 5 : 대조 표준 / 보고서에 차트가 정렬 설정 정렬 동작을 조정하는 다양한 옵션에 대해 설명합니다. 옵션 중 하나는 -kn-true또는 [numericOrdering on]:

on으로 설정하면 10 진수 숫자 시퀀스 ([ UAX44 ] 의 General_Category = Nd )가 기본 값에서 숫자 값으로 정렬됩니다. 예를 들어 "A-21"< "A-123"입니다. 계산 된 1 차 가중치는 모두 숫자 순서 변경 그룹 의 시작 부분에 있습니다. 따라서 조정되지 않은 UCA 테이블에서는 "a $"< "a0"< "a2"< "a12"< "a⓪"< "aa"입니다.

그러나이 문서는 "기술 표준"이며 핵심 유니 코드 사양의 일부가 아닙니다. 문서 상단의 메모는 다음과 같습니다.

UTS (Unicode Technical Standard) 는 독립적 인 사양입니다. 유니 코드 표준에 대한 적합성은 UTS에 대한 적합성을 의미하지 않습니다.

따라서이 특정 동작은 둘 다 핵심 유니 코드 사양을 준수하더라도 SQL Server 또는 .NET (적어도 기본적으로는 아님)에서는 사용할 수 없습니다.

ICU의 프로젝트 (유니 코드에 대한 국제 구성 요소) 구현이 기능, 그리고 심지어 온라인 데모가 있다고 C / C ++ 및 Java 라이브러리의 집합입니다. "관련 프로젝트"에는 ICU 라이브러리의 COM 객체 래퍼 인 .NET 프로젝트에 대한 링크가 있으며이 기능을 통해 관리되는 코드에이 기능을 제공 할 수 있습니다. 그러나 해당 .NET 프로젝트가 여전히 활성화되어 있는지 확실하지 않습니다.

그러나이 동작을 실제로 보려면 ICU Collation Demo 로 이동하십시오 .

왼쪽 의 입력 텍스트 영역에 다음을 붙여 넣습니다 .

1
2
10B
6
11
10A
3
10

모든 옵션을 "default"로 설정하십시오. sort버튼 오른쪽의 "입력 라인 번호"옵션을 확인하고 "diff strengths"옵션이 선택 해제되어 있는지 확인하십시오.

sort버튼을 클릭하면 다음과 같이 돌아옵니다.

[1] 1
[8] 10
[6] 10A
[3] 10B
[5] 11
[2] 2
[7] 3
[4] 6

이것은 일반적인 문자열 정렬을 수행 할 때 예상되는 것과 SQL Server에 표시되는 것입니다.

이제 버튼 바로 위의 일련의 라디오 버튼 sort에서 두 번째 행에는 "숫자"라는 레이블이 붙어 있습니다. "켜기"라디오 버튼을 선택하십시오.

sort버튼을 다시 클릭하면 다음과 같이 돌아옵니다.

[1] 1
[2] 2
[7] 3
[4] 6
[8] 10
[6] 10A
[3] 10B
[5] 11

숫자 부분이 문자열의 중간에있을 때 이것이 작동하는지 질문합니까? 다음을 왼쪽 의 입력 텍스트 영역에 붙여 넣습니다 (이전 목록 대체).

Script - 1.sql
Script - 2.sql
Script - 10B.sql
Script - 6.sql
Script - 11.sql
Script - 10A.sql
Script - 3.sql
Script - 10.sql

숫자 설정이 여전히 "on"으로 설정되어 있는지 확인하십시오 . sort버튼을 다시 클릭하면 다음과 같이 돌아옵니다.

[1] Script - 1.sql
[2] Script - 2.sql
[7] Script - 3.sql
[4] Script - 6.sql
[8] Script - 10.sql
[6] Script - 10A.sql
[3] Script - 10B.sql
[5] Script - 11.sql

다른 곳에서 이것을보고 싶습니까? 하드 드라이브에 C : \ temp \ sorting \ 과 같은 폴더를 만들고 동일한 "Script -..."이름의 빈 파일을 만듭니다. 를 수행 DIR명령 창에서 당신은 표준 정렬을 볼 수 있습니다. 그러나 Windows 탐색기에서 파일 목록을 볼 때 "숫자"옵션 (-)을 사용하여 정렬 된 목록을 볼 수 있습니다.


참고로 Postgres 10은 ICU 데이터 정렬을 지원합니다. Peter Eisentraut 의이 블로그 게시물 을 참조하십시오 .
Basil Bourque

@BasilBourque PG10에 대해 언급 해 주셔서 감사합니다. 마지막으로이 블로그 포스트는 "ICU는 PostgreSQL을 통해 아직 노출하지 않은이 영역에서 많은 기능을 제공합니다. 대소 문자를 구분하지 않는 정렬, 악센트를 구분하지 않는 정렬 및 데이터 정렬을 완전히 사용자 정의하는 옵션이 있습니다. 향후 PostgreSQL 릴리스의 사용자에게 적합합니다. " 따라서 첫 번째 / 현재 구현에서는 내 답변의 정보가 변경되지 않습니다. 향후 제공이 숫자 정렬을 허용하는 경우 대답에서 언급하지만이 질문은 SQL Server 관련이므로 각주로 언급됩니다.
Solomon Rutzky
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.