3

以前に投稿された質問には回答がありませんでした。そのため、この MySQL マニュアル エントリに基づいて、私の研究結果からさらに明確な説明と詳細に置き換えています。

過去に、代替の既定の並べ替えを指定できる代替照合を使用してきました。Mysql ではこれを列レベルまで可能にしていますが、それを機能させる方法がわかりませ

当社のお客様は、マスター テーブルへのほぼすべての参照で 1 文字コードの標準セットを使用しており、これらのコードを必要な順序で提示することは、常に非常に面倒で、PHP の関数やルーチンを使用するのが困難です。

SELECT * FROM myTable order by my_code

NORMAL, default sorting would return this:      DESIRED, default sorting should return this:
my_code | Description                           my_code | Description
 1      | Grade 1                               P  | Pre-Kindergarten
 2      | Grade 2                               K  | Kindergarten
 3      | Grade 3                               1  | Grade 1
 A      | Adult                                 2  | Grade 2
 K      | Kindergarten                          3  | Grade 3
 P      | Pre-Kindergarten                      A  | Adult

これを行う手順は、10.4.3 のドキュメントに記載されています。、および例は10.1.78 のドキュメントに示されています。

手順では、この表と重みの指定方法を示します。これは、私が迷っているところだと思います。以下のようにウェイトを変更し、「P」(x50P) と「K」(x4B) を「0」(x30) の前に置きましたが、「1」(x31) が間に現れるようにソートを変更しただけです。 「P」と「K」、他のすべての並べ替えは変更されていないように見えます。

<collation name="latin1_test_ci">
<map>
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
50 4B 30 31 32 33 34 35 36 37 38 39 41 43 55 3A
3B 3C 3D 3E 3F 40 42 44 45 46 47 48 49 4A 4C 4D
4E 4F 51 52 53 54 56 57 58 59 5A 5B 5C 5D 5E 5F
60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
44 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
44 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
</map>
</collation>

上記の代替照合で結果を並べ替える

Hex |my_code | Description
 32 |  2     |Grade 2
 33 |  3     |Grade 3
 41 |  A     |Adult Ed
 4B |  K     |Kindergarten
 31 |  1     |Grade 1
 50 |  P     |Pre-K
4

3 に答える 3

2

この表は重み表です。P i を K 未満にしたい場合は、P に 00 の重みを付け、K に 01 の重みを付けます。重みを付けるには、「文字の位置」に値を割り当てる必要があります: P の位置 50 の場合。P最初の順序の文字として配置するサンプル:

<collation name="latin1_test_ci">
<map>
FF FF FF FF FF FF FF 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
00 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F   <-- first weight
80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
44 4E 4F 4F 4F 4F 5C D7 5C 55 55 55 59 59 DE DF
41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
44 4E 4F 4F 4F 4F 5C F7 5C 55 55 55 59 59 DE FF
</map>
</collation>

編集:テストと競合テーブルを追加します。

の完全な表は次のようになります。

<collation name="latin1_test_ci">
<map>
 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
 30 02 03 04 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
 40 05 42 43 44 45 46 47 48 49 4A 01 4C 4D 4E 4F
 00 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
 A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
 41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
 44 4E 4F 4F 4F 4F 5C D7 5C 55 55 55 59 59 DE DF
 41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
 44 4E 4F 4F 4F 4F 5C F7 5C 55 55 55 59 59 DE FF
</map>
</collation>

* テスト: *

mysql> create table  b (a varchar(1) collate latin1_test_ci );

mysql> insert into b values
    -> ( 'P' ),
    -> ('K'),
    -> ('A'),
    -> ('1'),
    -> ('2'),
    -> ('3');


mysql> SHOW COLLATION LIKE 'latin1_test_ci';
+----------------+---------+----+---------+----------+---------+
| Collation      | Charset | Id | Default | Compiled | Sortlen |
+----------------+---------+----+---------+----------+---------+
| latin1_test_ci | latin1  | 56 |         |          |       0 |
+----------------+---------+----+---------+----------+---------+
1 row in set (0.00 sec)

mysql> select * from b order by a;
+------+
| a    |
+------+
| P    |
| K    |
| 1    |
| 2    |
| 3    |
| A    |
+------+
6 rows in set (0.00 sec)
于 2012-07-15T20:39:30.823 に答える
2

照合順序を変更したいとおっしゃいましたが、これは不要ORDER BYであり、検討する価値があります。これらを型に変換するENUMと、 に表示される順序で並べ替えられますENUM

CREATE TABLE myTable (
    my_code ENUM('P', 'K', '1', '2', '3', 'A'), 
    ...
)

ENUM で数値を使用することは強く推奨されないため、注意が必要です。主な問題は、数値がインデックスまたは ENUM の値として扱われる可能性があることです。そのため、その動作はそのタイプに依存し、予期しない結果につながります。

于 2012-07-15T17:39:51.973 に答える
1

目標を達成するためにカスタム照合は必要ないと思います。

結果セットを並べ替えるには:

ORDER BY FIELD(my_code, 'P','K','1','2','3','4','5','6',
    '7','8','9','10','11','12','A')

結果セットを制限するには:

 WHERE my_code IN('K','1','2','3','4','5')

この種の機能を多くのクエリに書き込む場合は、ヘルパー関数を使用することをお勧めします。

DELIMITER $$
CREATE FUNCTION `f_position`(in_char CHAR(1)) RETURNS INTEGER
BEGIN
    RETURN FIELD(in_char, 'P','K','1','2','3','4','5','6',
        '7','8','9','10','11','12','A');
END$$
DELIMITER ;

すべての可能なコードが関数で参照され、必要な順序で配置されていることを確認してください。

そのようなヘルパー関数を使用すると、次のようにクエリを記述できます。

WHERE f_position(grade) BETWEEN f_position('K') AND f_position('5')
ORDER BY f_position(grade)

ヘルパー関数を使用して結果セットを ( とは対照的に) 制限することの唯一の欠点WHERE grade IN(...)は、関数呼び出しによって、列 "grade" のインデックスが使用されなくなることです。

于 2012-06-15T17:40:14.303 に答える