사용자가 기대하는 알파와 숫자의 혼합 목록을 정렬하고 표시하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/552053

문제

우리의 응용 프로그램에는 a가 있습니다 CustomerNumber 필드. 우리는 시스템을 사용하는 수백 명의 다른 사람들이 있습니다 (각각 자체 로그인과 자체 목록이 있습니다. CustomerNumber에스). 개별 사용자는 최대 100,000 명의 고객을 가질 수 있습니다. 많은 사람들은 100 미만입니다.

어떤 사람들은 실제 숫자 만 고객 번호 필드에만 넣고 다른 사람들은 혼합물을 사용합니다. 이 시스템은 AZ, 0-9 또는 대시 일 수있는 20자를 허용하고 Varchar2 (20)에 저장합니다. 저장되기 전에 소문자가 대문자로 만들어집니다.

이제 고객 번호별로 정렬 된 특정 사용자의 모든 고객을 나열하는 간단한 보고서가 있다고 가정 해 봅시다. 예를 들어

SELECT CustomerNumber,CustomerName
FROM Customer
WHERE User = ?
ORDER BY CustomerNumber;

이것은 숫자 만 사용하는 사람들이 평범한 알파벳 정렬을보고 싶지 않기 때문에 순진한 솔루션입니다 ( "10"은 "9"이전에 온다).

나는 사용자에게 그들의 데이터에 대한 불필요한 질문을하고 싶지 않습니다.

나는 Oracle을 사용하고 있지만 다른 데이터베이스에 대한 몇 가지 솔루션을 보는 것이 흥미로울 것이라고 생각합니다. 답변이 작동하는 데이터베이스를 포함하십시오.

이것을 구현하는 가장 좋은 방법은 무엇이라고 생각하십니까?

도움이 되었습니까?

해결책

Oracle 10G에서 :

SELECT  cust_name
FROM    t_customer c 
ORDER BY
    REGEXP_REPLACE(cust_name, '[0-9]', ''), TO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+'))

이것은 숫자의 첫 번째 발생에 의해 정렬 될 것입니다.

  1. customer1 < customer2 < customer10
    • cust1omer ? customer1
    • cust8omer1 ? cust8omer2

, 여기서 a ? 주문이 정의되지 않았 음을 의미합니다.

그것은 대부분의 경우 충분합니다.

케이스에 정렬 순서를 강요합니다 2, 당신은 추가 할 수 있습니다 REGEXP_INSTR(cust_name, '[0-9]', n) 에게 ORDER BY 목록 n 시간, 첫 번째 모습에 대한 순서를 강요합니다 n-TH (2nd, 3rd 등) 숫자 그룹.

케이스에 정렬 순서를 강요합니다 3, 당신은 추가 할 수 있습니다 TO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+', n)) 에게 ORDER BY 목록 n 시간, 강제 순서 n-TH. 숫자 그룹.

실제로, 내가 쓴 쿼리만으로도 충분합니다.

이러한 표현식에 대한 기능 기반 색인을 만들 수 있지만 힌트와 1 패스로 강제로 강제해야합니다. SORT ORDER BY 어쨌든 어쨌든 수행됩니다 CBO 기능 기반 인덱스를 충분히 신뢰하지 않습니다 ORDER BY 그들에게.

다른 팁

아마도 가장 좋은 방법은 별도의 열을 사전 계산하고 주문에 사용하고 고객 번호를 표시하는 데 사용하는 것입니다. 이것은 아마도 내부 정수를 고정 길이로 0 패딩하는 것과 관련이있을 것입니다.

다른 가능성은 반환 된 결과에 대해 사후 선택을 정렬하는 것입니다.

Jeff Atwood는 블로그를 작성했습니다 일부 사람들이 인간 친화적 인 정렬 주문을 계산하는 방법에 대한 게시.

CustomerNumber가 순수한 숫자 일 때만 사용되는 숫자 열 [CustomerNumberInt]을 가질 수 있습니다 (그렇지 않으면 [1]).

ORDER BY CustomerNumberInt, CustomerNumber

1] SQL 버전을 순서대로 널을 처리하는 방법에 따라 기본값으로 0으로 기본값 (또는 무한대!)을 원할 수 있습니다.

나는 비슷한 끔찍한 상황을 가지고 있으며 그것을 다루기 위해 적절하게 끔찍한 기능을 개발했습니다 (sqlserver)

내 상황에서 나는 "단위"테이블을 가지고 있습니다 (이것은 학생들을위한 작업 추적 시스템 이므로이 맥락에서 단위는 그들이하는 과정을 나타냅니다). 유닛에는 코드가 있는데, 대부분의 경우 순전히 숫자이지만 여러 가지 이유로 Varchar가 만들어졌으며 일부는 최대 5 자까지 일부 접두사로 결정했습니다. 따라서 그들은 53,123,237,356이 정상적으로 정렬 될 것으로 예상하지만 T53, T123, T237, T356도 기대합니다.

UnitCode는 Nvarchar (30)입니다.

기능의 본문은 다음과 같습니다.

declare @sortkey nvarchar(30)

select @sortkey = 
    case
        when @unitcode like '[^0-9][0-9]%' then left(@unitcode,1) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-1)
        when @unitcode like '[^0-9][^0-9][0-9]%' then left(@unitcode,2) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-2)
        when @unitcode like '[^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,3) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-3)
        when @unitcode like '[^0-9][^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,4) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-4)
        when @unitcode like '[^0-9][^0-9][^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,5) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-5)
        when @unitcode like '%[^0-9]%' then @unitcode
        else left('000000000000000000000000000000',30-len(@unitcode)) + @unitcode
    end 

return @sortkey

글을 쓰고 나서 얼굴을 쏘고 싶었지만 서버가 실행될 때 서버를 죽이지 않는 것 같습니다.

나는 이것을 SQL Server에서 사용했고 훌륭하게 작동합니다. 여기서 솔루션은 모든 문자열 길이가되도록 숫자 값을 앞면의 숫자 값을 앞쪽으로 채우는 것입니다.

다음은 해당 접근법을 사용하는 예입니다.

select MyCol
from MyTable
order by 
    case IsNumeric(MyCol) 
        when 1 then Replicate('0', 100 - Len(MyCol)) + MyCol
        else MyCol
    end

100은 해당 열의 실제 길이로 교체해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top