在MySQL中按特殊字符排序

3
我在MySQL中对选定内容进行排序时遇到了问题。有些名字以"A"、"Á"、"Z"和"Ž"开头,只举几个例子。奇怪的是,“A”和“Á”被排序为相同的字母,而不是分别作为两个不同的字母。这意味着可能会像这样显示:
  • Aak
  • Adv
  • Ága
  • Agg
  • Ahm
我知道Á是A的子字母,但我希望它们可以分组,所以所有的A都排在前面,然后才是Á。 该字段的排序规则为utf8mb4_unicode_ci。
我做错了什么?
更新: 如果Á被视为A的相同字母,则排序是正确的,因为它会查看下一个字母等等。但我想让Á与A分开,所以它应该像这样排序:
  • Aak
  • Adv
  • Agg
  • Ahm
  • Ága

哪个服务器版本? - Paul Spiegel
但是你需要它是UTF格式的吗? - Paul Spiegel
我的意思是它使用latin1工作:order by convert(word using latin1) collate latin1_general_ci; https://www.db-fiddle.com/f/8yZu6eWWpoesk8yBWruPWM/0 - Paul Spiegel
它将 A A A Á Á B C 进行排序。 - Paul Spiegel
你可以尝试其他的拉丁字符集/排序规则,比如latin2_czech_cs,你需要支持哪些语言? - Paul Spiegel
显示剩余5条评论
1个回答

0
以下三种针对UTF8MB4字符集的排序规则看起来很有前途,即utf8mb4_icelandic_ciutf8mb4_is_0900_ai_ciutf8mb4_is_0900_as_cs。使用@Paul Spiegel的示例得到的结果如下:
word
====
Ab
Ac
Ae
Ád
Áf
Ba
Ca
Št
Zo
Žv

db-fiddle code

我通过使用PROCEDURE来检查可用的排序规则,对它们进行了识别。

CREATE PROCEDURE `Try_Collation`()
BEGIN

DECLARE v_finished INTEGER DEFAULT 0;
DECLARE c_collation varchar(100) DEFAULT "";

-- read available collations for utf8mb4
DECLARE table_cursor CURSOR FOR 
    SELECT COLLATION_NAME 
    FROM INFORMATION_SCHEMA.COLLATIONS
    WHERE CHARACTER_SET_NAME='utf8mb4';

DECLARE CONTINUE HANDLER 
    FOR NOT FOUND SET v_finished = 1;

OPEN table_cursor;

    Loop_label: LOOP -- test individual collations by loop

    -- read one collation to table_cursor
    FETCH table_cursor INTO c_collation;

    IF v_finished = 1 THEN 
        LEAVE Loop_label;
    END IF;
    
    -- save the ordered table to a temp table
    DROP TEMPORARY TABLE IF EXISTS temp_table;
    CREATE TEMPORARY TABLE temp_table (
        `word` varchar(50)
        );

    SET @s=CONCAT(
        "INSERT INTO temp_table ",
        "(select word from test ",
        "order by convert(word using utf8mb4) ",
        "collate ",c_collation,");");
    
    PREPARE stmt FROM @s;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    
    -- set some filtering rules for checking orders
    IF (select word from temp_table limit 2,1)='Ád' THEN
        ITERATE Loop_label; -- skip to next loop iteration
    END IF;
    IF (select word from temp_table limit 5,1)='Zo' THEN
        ITERATE Loop_label; -- skip to next loop iteration
    END IF;
    
    SELECT c_collation; -- print out current collation
    SELECT * FROM temp_table; -- print out ordered table

    END LOOP Loop_label;

CLOSE table_cursor;

END;

CALL Try_Collation();

代码链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接