数据库
首页 > 数据库> > mysql – 在字符串列上使用asc和desc的索引

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