MySQL - 选择第一个字符是小写还是大写
Posted
技术标签:
【中文标题】MySQL - 选择第一个字符是小写还是大写【英文标题】:MySQL - Select where first character is lowercase or uppercase 【发布时间】: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'
【参考方案1】:
您可以使用Ascii()
函数。它返回输入字符串最左边字符的数值。
对于第一个小写字符:a
的 ASCII 码是 97,z
是 122。所以,第一个字符的 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 码是 65,Z
是 90。所以,第一个字符的 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
的单词,例如zahn
或zzzzzzzzz
。
上述查询的有效补丁是使用 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
【讨论】:
以上是关于MySQL - 选择第一个字符是小写还是大写的主要内容,如果未能解决你的问题,请参考以下文章
javajava 实现 将 字符串 第一个字符 大写 或者 小写
如何通过 js 仅将第一个字符小写所有字符和大写? [复制]