2009-05-07 6 views
19

데이터베이스의 열의 첫 문자를 모두 문자 목록으로 생성하고 싶습니다. 아래 illistrats 아래의 SQL은 내가 무엇을 반환하고 싶습니다.필드의 DISTINCT 첫 번째 문자 반환 (MySQL)

 
SELECT DISTINCT first_character(name) FROM mydatabase 

MySQL에서이 작업을 수행 할 수있는 방법이 있습니까?

편집 LEFT보다 SUBSTRING을 사용하면 어떤 점이 좋고 그 반대의 경우가 있습니까?

편집 현재 약 1700 개의 레코드가 테이블에 있습니다.

select distinct substring(field,1,1) as char 
from mytable 
+1

테이블에 몇 개의 레코드가 있습니까?나는 최적화 된 버전을 게시하고 싶지만 성가신 여부를 모른다 : – Quassnoi

+0

좋아, 어쨌든 그것을 게시 :) 아마 내일 내 블로그에 귀하의 질문에 게시물을 만들거야. – Quassnoi

답변

55

미안이 작업을 수행하는 것이 아니라 내가 지금 할 필요가 정확히 파악 :

+0

자신의 질문에 대한 답변을 게시하는 것이 좋습니다. +1 –

+0

SQL 표준이기 때문에'SUBSTRING() '을 사용합니다. LEFT() 함수의 표준을 찾지 못했습니다. http://troels.arvin.dk/db/rdbms/#functions-SUBSTRING – Sonny

9

은 간단 소리.

 
SELECT DISTINCT LEFT(name, 1) FROM mydatabase 

이렇게하면 열의 각 행이 시작된 첫 번째 별개의 단일 문자 목록이 반환됩니다. 나는 그것을 다음과 같이 변경하여 영숫자 순으로 목록을 만들었습니다.

 
SELECT DISTINCT LEFT(name, 1) as letter FROM mydatabase ORDER BY letter 

매력처럼 작동합니다.

+1

SQL 표준 사용법 :'SUBSTRING (시작 위치 [FOR 길이])'->'SUBSTRING (필드 FROM 1 FOR 1) ' – Sonny

+0

@Sonny :'FROM '키워드 근처의 구문이 올바르지 않습니다. – Andomar

+0

내가 왜 "틀린 문법"을 게시했는지 모르겠습니다. 여기에 게시 된 구문이 나와 있습니다. http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substring - 전체 쿼리 'DISTINCT SUBSTRING (field FROM 1 FOR 1) AS char from mytable' – Sonny

9

1,700 행의 현재 테이블에 대한 솔루션은 정상입니다.

행 수가 100,000 인 경우 DISTINCT은 비효율적 일 수 있습니다.

이 솔루션은 name에 인덱스를 사용 :

여기에 효율적으로 작업을 수행하는 방법을 보여줍니다 내 블로그에있는 문서입니다. 첫 번째 문자를 한 번만 선택하면 색인 키 위로 이동합니다.

첫째, 함수를 만들어야합니다 :

CREATE FUNCTION fn_get_next_code(initial INT) RETURNS INT 
NOT DETERMINISTIC 
READS SQL DATA 
BEGIN 
     DECLARE _next VARCHAR(200); 
     DECLARE EXIT HANDLER FOR NOT FOUND RETURN NULL; 
     SELECT ORD(SUBSTRING(name, 1, 1)) 
     INTO _next 
     FROM t_names 
     WHERE name >= CHAR(initial + 1) 
     ORDER BY 
       name 
     LIMIT 1; 
     RETURN _next; 
END 

이 기능은 시작 문자 코드 주어진 테이블에서 주어진 옆의 첫 시작 문자를 반환합니다.

둘째, 쿼리에서이 기능을 사용

SELECT CHAR(@r) AS starting, 
     @r := fn_get_next_letter(@r) AS next 
FROM (
     SELECT @r := ORD(LEFT(MIN(name), 1)) 
     ) vars, mytable 
WHERE @r IS NOT NULL 

를 각각의 반복에서 세션 변수 @r는 인덱스를 사용하여 다음 시작 문자를 건너 뜁니다.

이것은 매우 빠르지 만 수십만 개의 행이있는 경우에만 비용을 지불합니다.

그렇지 않으면 DISTINCT을 사용하십시오.

+0

우주에있는 모든 명명 된 엔티티의 UN 테이블을 조회해야 할 때 북마크했습니다. D – Andomar

+0

US ASCII, 유니 코드에서 테스트하지 않았다 :) – Quassnoi

관련 문제