mysql – 在字符串列上使用asc和desc的索引
作者:互联网
当我们想要通过asc和desc订购时,我知道一个通过查询更快地进行排序的技巧.
对于整数存储否定值.
因此,如果我存储-7,-11,-8,-5,-1,-2,则asc的顺序将给出-11,-8,-7,5,-2,-1,因此实际的行将是按该列排序desc(例如,如果我显示非否定版本).
问题:如何在字符串中使用此技巧?
如何将字符串“否定”或反转,以便该字符串也适用于字符串列?
更新
MySQL无法使用索引进行类型的查询:
ORDER BY col1 ASC col2 DESC
如果我想要下降的列是一个整数,我可以存储否定值并执行以下查询:
ORDER BY col1 ASC col2 ASC
在这种情况下,可以使用索引,实际上由于否定-11,-8,-7,5,-2,-1升序,我将按降序获取值,但是如果删除否定则是降序.
我的问题是我不清楚如何将这种方法应用于字符串列.我可以以某种方式获得字符串的算术值吗?
解决方法:
虽然CREATE INDEX的语法支持将索引定义为升序或降序的选项,但在最常见的两个存储引擎(InnoDB和MyISAM)中,此索引选项是无操作.没有“升序”或“降序”索引,它们只是索引,可以用于任何方向的排序.
但是在你描述的情况下,你有一个多列索引,你想按一列升序排序而另一列降序,这是一个不同的故事.如果列使用索引,则排序顺序必须在两个列的相同方向上.
(并不是说每种方法都必须使用索引.您当然可以运行查询并让它使用filesort对匹配的行进行排序.)
要反转字符串的排序顺序,可以添加自己的自定义排序规则. https://dev.mysql.com/doc/refman/5.6/en/adding-collation.html
但是您必须使用新的排序规则来存储字符串,并重建索引.该索引仅对反向排序有用.
来自@Cratylus的评论:
整理是将“A”定义为在“B”之前以及所有其他字母顺序.因此,如果您定义一个表示“B”在“A”之前的排序规则,并在列定义中使用该排序规则,那么对该列进行排序或在列上创建索引将采用相反的顺序.
注意:以下内容不会创建正确的排序规则,它只是演示了创建排序规则的步骤.
>编辑/usr/share/mysql/charsets/Index.xml并进行此编辑:
<charset name="latin1">
. . . leave other collations alone . . .
<collation name="latin1_reverse_ci" id="251">
<order>Dutch</order>
<order>English</order>
<order>French</order>
<order>German Duden</order>
<order>Italian</order>
<order>Latin</order>
<order>Portuguese</order>
<order>Spanish</order>
</collation>
</charset>
>编辑/usr/share/mysql/charsets/latin1.xml并进行此编辑:
<charset name="latin1">
. . . leave other collations alone . . .
<collation name="latin1_reverse_ci">
<map>
AE B1 AC A2 A0 9E 9C 8D BE 8B 89 87 85 83 7F 59
73 71 6F 6D 63 61 5F 5D 55 4F 4D 4B 49 47 45 43
97 B1 AC A2 A0 9E 9C 8D BD 8B 89 87 85 83 7F 59
73 71 6F 6D 63 61 5F 5D 55 4F 4D 4B 49 47 45 43
FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0
EF EE ED EC EB EA E9 E8 E7 E6 E5 E4 E3 E2 E1 E0
DF DE DD DC DB DA D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
CF CE CD CC CB CA C9 C8 C7 C6 C5 C4 C3 C2 C1 C0
BF BC BB BA B9 AF AA A8 A6 A4 9A 98 95 93 91 8F
81 7D 7B 79 77 75 6B 69 67 65 5B 57 53 51 41 B8
B7 B6 B5 B4 B3 AF AA A8 A6 A4 9A 98 95 93 91 8F
81 7D 7B 79 77 75 6B 69 67 65 5B 57 53 51 41 40
3F 3E 3D 3C 3B 3A 39 38 37 36 35 34 33 32 31 30
2F 2E 2D 2C 2B 2A 29 28 27 26 25 24 23 22 21 20
1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10
0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
</map>
</collation>
</charset>
. . .
>重启mysqld.
>确认您有新的排序规则:
mysql> SHOW COLLATION LIKE 'latin1%';
+---------------------+---------+-----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+---------------------+---------+-----+---------+----------+---------+
. . .
| latin1_general_ci | latin1 | 48 | | Yes | 1 |
| latin1_general_cs | latin1 | 49 | | Yes | 1 |
| latin1_spanish_ci | latin1 | 94 | | Yes | 1 |
| latin1_reverse_ci | latin1 | 251 | | | 0 |
. . .
>创建一个表并用一些文本填充它:
mysql> CREATE TABLE foo (
id INT AUTO_INCREMENT PRIMARY KEY,
t VARCHAR(60) COLLATE latin1_reverse_ci,
x DATE,
KEY(t)
);
mysql> INSERT INTO foo (t) VALUES ('Harry'), ('Ron'), ('Hermione');
>证明排序顺序与您认为应该是的相反:
mysql> SELECT * FROM foo ORDER BY t ASC;
+----+----------+------+
| id | t | x |
+----+----------+------+
| 2 | Ron | NULL |
| 3 | Hermione | NULL |
| 1 | Harry | NULL |
+----+----------+------+
>确认它不使用filesort:
mysql> EXPLAIN SELECT * FROM foo WHERE t LIKE 'H%' ORDER BY t\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: foo
partitions: NULL
type: range
possible_keys: t
key: t
key_len: 63
ref: NULL
rows: 2
filtered: 100.00
Extra: Using index condition
我不得不在行上添加条件,因为否则它会认为它将读取表中的所有行,并且它执行了表扫描和文件输出.
来自@ypercube的评论:
它不会像REVERSE()那样反转给定字符串中字符的顺序,它会在比较两个字符串时反转哪些字符被认为大于或小于彼此.所以不,CHAR填充空格无关紧要,它们仍然在两个字符串的末尾.
示例(这次没有索引,仅使用顺序):
mysql> create table t (c char(20) collate latin1_reverse_ci);
mysql> insert into t values ('A'), ('B'), ('C');
mysql> select * from t order by c;
+------+
| c |
+------+
| C |
| B |
| A |
+------+
编辑:不,@ yycube是正确的,这对CHAR不起作用,因为空格字符位于错误的位置,当我简单地通过将所有字节按相反的顺序重新排序来重新排序整理.这不是设计校对的正确方法.
所以这个答案应该作为创建整理的机制的演示,而不是作为逆转字母顺序的正确整理.
标签:mysql,string,index,order-by 来源: https://codeday.me/bug/20190806/1597399.html