대부분의 문자열 비교는 기본적으로 ASCIIbetical sorting으로 알려져 있습니다. 각 문자를 ASCII 번호 (또는 처음 7 비트는 ASCII와 겹치는 UTF-8)로 변환 한 다음 정렬합니다. 이 은 ... 잘 정렬 보인다
select 'a' < 'z'; -- true
...하지만 빨리 잘못.
select 'a' < 'Z'; -- false
대문자가 모두 ASCII의 모든 소문자와 UTF-8 뒤에 있기 때문입니다.
간단한 수정 방법은 양쪽에서 upper
또는 lower
을 호출하여 사례를 표준화하는 것입니다. ASCIIbetical 정렬과
select lower('a') < lower('Z'); -- true
두 번째 문제는 숫자입니다. 다시, 그것은 밖으로 시작됩니다 ...
select 'a9' < 'a1'; -- true
...하지만 빠르게 냄비에 간다.
select 'a9' < 'a10'; -- false
ASCIIbetical 정렬은 한 번에 한 문자 씩 비교합니다. ASCII 9 (57)는 ASCII 1 (49)보다 작습니다.
은 당신이 원하는 것은 문자열과 숫자는 숫자로 비교로 문자열 부분이 비교되는 natural sort이다. SQL에서 자연 정렬을하는 것은 쉬운 일이 아닙니다. 각각의 부분 문자열을 개별적으로 정렬하기 위해 고정 된 필드 너비가 필요하거나 정규식을 사용하여 뭔가를 정렬 할 필요가 있습니다 ...
다행히도 효율적인 자연 정렬을 구현하는 Postgres 확장자가 pg_natural_sort_order입니다.
확장 프로그램을 설치할 수없는 경우 btrsort by 2kan과 같은 저장 프로 시저를 사용할 수 있습니다.
CREATE FUNCTION btrsort_nextunit(text) RETURNS text AS $$
SELECT
CASE WHEN $1 ~ '^[^0-9]+' THEN
COALESCE(SUBSTR($1, LENGTH(SUBSTRING($1 FROM '[^0-9]+'))+1), '')
ELSE
COALESCE(SUBSTR($1, LENGTH(SUBSTRING($1 FROM '[0-9]+'))+1), '')
END
$$ LANGUAGE SQL;
CREATE FUNCTION btrsort(text) RETURNS text AS $$
SELECT
CASE WHEN char_length($1)>0 THEN
CASE WHEN $1 ~ '^[^0-9]+' THEN
RPAD(SUBSTR(COALESCE(SUBSTRING($1 FROM '^[^0-9]+'), ''), 1, 12), 12, ' ') || btrsort(btrsort_nextunit($1))
ELSE
LPAD(SUBSTR(COALESCE(SUBSTRING($1 FROM '^[0-9]+'), ''), 1, 12), 12, ' ') || btrsort(btrsort_nextunit($1))
END
ELSE
$1
END
;
$$ LANGUAGE SQL;
비록 비교 연산자를 제공하지는 않지만 그것을 이해하는 척하지는 않을 것입니다. 이를 통해 order by
에서 사용할 수 있습니다.
select * from things order by btrsort(whatever);
는, 큰 테이블에 진흙
you can create a btree index on the result of that function 회전에서 자연적으로 분류 쿼리를 방지합니다.
create index things_whatever_btrsort_idx ON things(btrsort(whatever));
'select'a '<'b ';'는 postgres 9.6.1에서 True로 표시됩니다. 6.2 (5a) '<'6.2 (5b) ';는 참을 반환한다. 6.2 (15) '<'6.2 (5a) '; 또한 True를 반환합니다. 마지막 문자는'6.2 ('일치하고 다음 문자''1 '<'5''과 6.2 (15)가 6.2 (5a)보다 작기 때문에 사실입니다.) – zedfoxus
사실 그게 사실입니다. '6.2 (15)'<6.2 (5a)>가 실제로 돌아 왔음을 알리는 후자의 비교는 당신이 그것을 지적하기 전까지는 알지 못했다. '15'는 '5a'보다 더 큽니다. 먼저 문자를 테스트하고 제거하고 숫자 문자열을 테스트 할 수 있습니까? – bakamike
[PostgreSQL ORDER BY 발행물 - 자연 정렬] 가능한 중복 (http://stackoverflow.com/questions/9173558)/postgresql-order-by-issue-natural-sort) – Schwern