【问题标题】:MySQL - Select where first character is lowercase or uppercaseMySQL - 选择第一个字符是小写还是大写
【发布时间】:2019-04-03 10:47:01
【问题描述】:

对不起,如果这是之前提出的问题,但我无法找到答案。 如何创建 MySQL 选择语句以从数据库中选择第一个字符为小写或大写的所有字符串。

我通常会使用这样的方法从英文单词数据库中随机选择 10 个长度超过 8 个字符的单词:

SELECT word FROM en_dictionary WHERE CHAR_LENGTH(word)>8 ORDER BY RAND() LIMIT 10

不幸的是,这也会选择我不希望在结果中出现的大写字母单词,因为它们通常是城市名称、物种名称等术语:

所以,我的问题是:有没有办法只选择以小写字母字符(或大写字母)开头的单词?

我可以做这样的事情并且它会起作用,但这是一个非常丑陋的陈述:

AND word LIKE BINARY 'a%' AND word LIKE BINARY 'b%' AND word LIKE BINARY 'c%'...

【问题讨论】:

  • word 列定义的字符集和排序规则是什么?
  • 我的设置:COLLATE='utf8_general_ci'

标签: mysql sql mariadb uppercase lowercase


【解决方案1】:

您可以使用Ascii() 函数。它返回输入字符串最左边字符的数值。

对于第一个小写字符a 的 ASCII 码是 97z122。所以,第一个字符的 ASCII 码应该在 97 到 122 之间。

SELECT word 
FROM en_dictionary 
WHERE CHAR_LENGTH(word) > 8 
  AND ASCII(word) BETWEEN 97 AND 122
ORDER BY RAND() LIMIT 10

对于第一个大写字符A 的 ASCII 码是 65Z90。所以,第一个字符的 ASCII 码应该在 65 到 90 之间。

SELECT word 
FROM en_dictionary 
WHERE CHAR_LENGTH(word) > 8 
  AND ASCII(word) BETWEEN 65 AND 90
ORDER BY RAND() LIMIT 10

【讨论】:

    【解决方案2】:

    不是一个完整的答案,但是对于一个评论来说太大了,所以我做了一个答案。

    我建议您使用区分大小写的 utf8 排序规则,例如 utf8_bin
    然后你不需要使用 BINARY 或其他 MySQL “hacks”来获得你需要的结果,你可以简单地使用 LIKE/BETWEEN 并区分大小写。

    创建表

    CREATE TABLE test (
    
        utf8_general_ci_word VARCHAR(255) COLLATE utf8_general_ci
      , utf8_bin_word VARCHAR(255) COLLATE utf8_bin
    );
    
    INSERT INTO test (utf8_general_ci_word, utf8_bin_word) VALUES('a', 'a');
    INSERT INTO test (utf8_general_ci_word, utf8_bin_word) VALUES('A', 'A');
    
    INSERT INTO test (utf8_general_ci_word, utf8_bin_word) VALUES('b', 'b');
    INSERT INTO test (utf8_general_ci_word, utf8_bin_word) VALUES('B', 'B');
    

    结果

    查询 #1

        SELECT 
         utf8_general_ci_word
        FROM
         test 
        WHERE
         utf8_general_ci_word LIKE 'a%'
    
        ;
    
    | utf8_general_ci_word |
    | -------------------- |
    | a                    |
    | A                    |
    

    查询 #2

        SELECT 
         utf8_general_ci_word
        FROM
         test 
        WHERE
         utf8_general_ci_word LIKE BINARY 'a%'
    
        ;
    
    | utf8_general_ci_word |
    | -------------------- |
    | a                    |
    

    查询 #3

        SELECT 
         utf8_bin_word
        FROM
         test 
        WHERE
         utf8_bin_word LIKE 'a%';
    
    | utf8_bin_word |
    | ------------- |
    | a             |
    

    demo

    所以您的查询将类似于

    查询

    SELECT
      word
    FROM
      en_dictionary
    WHERE
        CHAR_LENGTH(word) > 8
      AND
        word BETWEEN 'a' AND 'z'
    ORDER BY
     RAND()
    LIMIT 10
    

    demo on the test data

    于 2019 年 8 月 11 日编辑

    这会漏掉像“zahn”这样的词,因为它不是

    感谢 dnoeth 的评论和 2019 年 7 月 11 日晚些时候的一次较晚的陪练会议,在某些情况下,上面的 SQL 确实存在错误..

    由于word BETWEEN 'a' AND 'z'word >= 'a' AND word <= 'z' 的语法糖,这确实不会匹配大于z 的单词,例如zahnzzzzzzzzz。 上述查询的有效补丁是使用 REPEAT('<char>', <number_of_size_of_table_column_datatype>) 作为本例中的最大范围含义 word BETWEEN 'a' AND REPEAT('z', 255)

    补丁的demo..

    【讨论】:

    • 不应该是LEFT(word,1) Between 'a' and 'z'
    • "不应该是 LEFT(word,1) 在 'a' 和 'z' 之间吗" 不,我使用 MySQL 的字符串转换来发挥我的优势 @MadhurBhaiya 检查这个 db-fiddle.com/f/tCUgdpcwH7E78gviia6yqv/4 .. 除了 if word被索引我会失去最好的索引使用LEFT(word,1)db-fiddle.com/f/tCUgdpcwH7E78gviia6yqv/6
    • 有趣的+1;做了更多的实验:db-fiddle.com/f/tCUgdpcwH7E78gviia6yqv/7
    • 感谢@dnoeth 的这次较晚的陪练会议,它用补丁更新了答案,现在确实可以正确返回..
    • “不应该是 LEFT(word,1) between 'a' and 'z'” @MadhurBhaiya 查看更新后的答案,确实需要一个补丁才能让这适用于很久以前被忽视的所有情况:-) ...加上索引使用仍然是good
    【解决方案3】:

    您可以使用 SUBSTRING 和 REGEXP BINARY

    SELECT word 
    FROM en_dictionary 
    WHERE CHAR_LENGTH(word)>8 
    AND SUBSTRING(word, 1, 1) REGEXP BINARY '[A-Z]'
    ORDER BY RAND() LIMIT 10
    

    使用 REGEXP BINARY 您可以根据需要使用任何正则表达式,请参阅文档:https://dev.mysql.com/doc/refman/8.0/en/regexp.html

    SUBSTRING 只是为了获取第一个字母。

    How to check for uppercase letters in MySQL?

    MySQL Select Query - Get only first 10 characters of a value

    【讨论】:

      猜你喜欢
      • 2015-04-23
      • 1970-01-01
      • 2011-09-15
      • 2018-06-17
      • 2012-06-08
      • 2012-01-03
      • 2014-02-12
      • 2020-10-21
      • 1970-01-01
      相关资源
      最近更新 更多