2010-08-06 9 views
5

mysql 테이블에 열 (varchar (255))이 있는데,이를 "word"라고 부를 수 있습니다. 이 열의 값을 문자열의 문자로 정렬하여 반환하는 선택 쿼리를 작성하는 방법은 무엇입니까?MySQL에서 문자열 문자 정렬

예를 들어, 레코드 중 하나에 "earth"라는 단어가 있으면 모든 행에 대해 "aehrt"등을 반환해야합니다. 단일 쿼리에서이를 수행 할 수있는 방법이 있습니까?

+0

어떻게 복제본을 처리 하시겠습니까? "book"-> "bko"또는 "bkoo"? 관심이 없으면 왜이 작업을 수행해야합니까? –

+0

대소 문자를 구별하지 않습니까? –

+0

대소 문자를 구분하지 않습니다. –

답변

5
아마

매우 비효율적하지만, 사용자 정의 함수에 대한 필요없이 :

SELECT GROUP_CONCAT(LETTER SEPARATOR '') AS ReOrderedLetters 
    FROM (SELECT 'A' as LETTER FROM <table> WHERE UPPER(`name`) like '%A%' 
     UNION ALL 
     SELECT 'B' as LETTER FROM <table> WHERE UPPER(`name`) like '%B%' 
     UNION ALL 
     SELECT 'C' as LETTER FROM <table> WHERE UPPER(`name`) like '%C%' 
     UNION ALL 
     SELECT 'D' as LETTER FROM <table> WHERE UPPER(`name`) like '%D%' 
     ... 
     UNION ALL 
     SELECT 'Y' as LETTER FROM <table> WHERE UPPER(`name`) like '%Y%' 
     UNION ALL 
     SELECT 'Z' as LETTER FROM <table> WHERE UPPER(`name`) like '%Z%' 
     ) alpha 

편집 내가 자기 전에 더 나은 대안을 마련했다

, 그렇지 않으면 내가 좋겠 절대 잠들지 않아. 그래서 여기에 훨씬 더 깨끗하고 효율적인 대안이 있습니다.

문자라는 VARCHAR (1)의 단일 열이있는 letters라는 테이블을 만들었습니다.

select U.`name`, 
     GROUP_CONCAT(L.`letter` 
      ORDER BY L.`letter` ASC 
      SEPARATOR '') AS ReOrderedLetters 
    FROM `users` U 
    LEFT JOIN `letters` L ON POSITION(L.`letter` IN UPPER(U.`name`)) > 0 
GROUP BY U.`name` 
+0

우물 ... 나는 함수를 정의하고 싶습니다. –

+0

@Vinko - 제 수정 된 솔루션이 더 깨끗해지기를 바랍니다. –

+0

훨씬 좋아 졌어, 지금은 받아 들여진 대답처럼 보입니다. –

0

좋아 아이들 : 는 Z

다음
CREATE TABLE IF NOT EXISTS `letters` (
    `letter` varchar(1) NOT NULL, 
    PRIMARY KEY (`letter`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

INSERT INTO `letters` (`letter`) VALUES 
('A'),('B'),('C'),('D'),('E'),('F'),('G'),('H'),('I'),('J'),('K'),('L'),('M'), 
('N'),('O'),('P'),('Q'),('R'),('S'),('T'),('U'),('V'),('W'),('X'),('Y'),('Z'); 

에 문자 A를 해당 테이블을 채워집니다. 다음은 t-sql의 bubblesort 함수입니다. mysql으로 직접 변환 할 수있다. SQL Server가 실제로 재귀 함수를 좋아하지 않는다는 사실이 밝혀졌습니다. 그러나 실제로는 매우 빠르게 실행되었습니다.

Create Function bubblesort(@In varchar(255)) 
Returns varchar(255) 
AS 
BEGIN 
    Declare @Answer varchar(255) 
    Declare @swapped bit 
    Declare @Counter int 

    Set @Answer = @In; 
    --only need to sort strings longer than 1 
    if len(@Answer) > 1 
    BEGIN 
     While 1=1 
     BEGIN 
      Set @Counter = 1; 
      Set @swapped = 0; 
      While @Counter <= len(@Answer) - 1 
      BEGIN 
       If substring(@Answer, @Counter, 1) > substring(@Answer, @Counter + 1, 1) 
        BEGIN 
        --swap 
        Set @swapped = 1; 
        Set @Answer = Stuff(@Answer, @Counter, 2, reverse(substring(@Answer, @Counter, 2))); 
        END; 
       Set @Counter = @Counter + 1; 
      END; 
      if @swapped = 0 
      BREAK; 
     END; 
    END; 
    Return @Answer; 
END; 
go 

결과

Select ltrim(myfield) from mytable; 
1

그런 다음 각 임시 테이블로 각 단어의 문자와 GROUP_CONCAT()를 정렬을 s의 삽입을 손질하는 것을 잊지 마십시오. 이것은 아마도 커서의 사용과 모든 문자를 임시 테이블에 삽입하기 때문에 매우 효율적인 솔루션은 아닙니다. 나는 일종의 루틴이 더 빨라질 것이라고 내기는하지만 임시 테이블을 사용하지 않는다면 어떤 종류의 배열 구조가 필요하다. MySQL 프로 시저에 배열이 있는지 확실하지 않습니다.

delimiter $$ 
drop procedure if exists sort_letters$$ 
create procedure sort_letters() 
begin 
     declare done int default 0; 
     declare word varchar(256); 
     declare cur1 cursor for select i from a; 
     declare continue handler for not found set done = 1; 
     drop temporary table if exists temp; 
     create temporary table temp (id int, letter char); 
     set @wordcount = 0; 
     open cur1; 
     repeat 
       fetch cur1 into word; 
       if not done then 
         set @counter = 0; 
         set @len = length(word); 
         while (@counter <= @len) do 
           insert into temp values 
           (@wordcount, substring(word,@counter,1)); 
           set @counter = @counter + 1; 
         end while; 
         set @wordcount = @wordcount + 1; 
       end if; 
     until done end repeat; 
     close cur1; 
     select group_concat(letter order by letter separator '') 
     from temp group by id; 
end$$ 


mysql> desc a; 
+-------+--------------+------+-----+---------+-------+ 
| Field | Type   | Null | Key | Default | Extra | 
+-------+--------------+------+-----+---------+-------+ 
| i  | varchar(256) | YES |  | NULL |  | 
+-------+--------------+------+-----+---------+-------+ 
1 row in set (0.04 sec) 

mysql> select * from a; 
+-------+ 
| i  | 
+-------+ 
| earth | 
| sand | 
| fire | 
+-------+ 
3 rows in set (0.00 sec) 

mysql> call sort_letters(); 
+---------------------------------------------------+ 
| group_concat(letter order by letter separator '') | 
+---------------------------------------------------+ 
| aehrt            | 
| adns            | 
| efir            | 
+---------------------------------------------------+ 
3 rows in set (0.00 sec) 
1

각 문자를 한 번 나타내는 흥미로운 대안이 있습니다. 정확하게 확실하지 모든 문자를 표현하는 오버플로 오류의 일종을 유발하는 경우, 그러나 논리는 생각을위한 음식 :

분명히
SELECT 
CONCAT(
REPEAT('a',SIGN(POSITION('a' IN word_col))), 
REPEAT('b',SIGN(POSITION('b' IN word_col))), 
REPEAT('c',SIGN(POSITION('c' IN word_col))), 
REPEAT('d',SIGN(POSITION('d' IN word_col))), 
REPEAT('e',SIGN(POSITION('e' IN word_col))), 
REPEAT('f',SIGN(POSITION('f' IN word_col))), 
... 
REPEAT('Z',SIGN(POSITION('Z' IN word_col))) 
) 
FROM 
word 

는 "종류"는 CONCAT 구성 방식을 기반으로합니다.