MySQL 'Order By' - 英数字を正しくソートする

次のデータ項目を、以下に示す順番でソートしたい(数字1〜12)。

1
2
3
4
5
6
7
8
9
10
11
12

しかし、私のクエリは、 order by xxxxx asc を使って、他のすべての最初の数字でソートします。

1
10
11
12
2
3
4
5
6
7
8
9

より適切に並べ替えるための手口はありますか?

さらに、完全な開示のために、これは文字と数字が混在している可能性があります(現時点ではそうではありませんが)。

A1
534G
G46A
100B
100A
100JE

等....

ありがとう!

更新:クエリを求めるユーザー

select * from table order by name asc
45

12 答え

人々はこれを行うために別のトリックを使用します。私はグーグルで、それぞれ異なるトリックに従ったいくつかの結果を見つけます。彼らを見てみましょう:

編集:

私は、将来の訪問者のために各リンクのコードを追加しました。

MySQLでのアルファ数値ソート

指定の入力

1A 1a 10A 9B 21C 1C 1D

期待される出力

1A 1C 1D 1a 9B 10A 21C

クエリ

Bin Way
===================================
SELECT 
tbl_column, 
BIN(tbl_column) AS binray_not_needed_column
FROM db_table
ORDER BY binray_not_needed_column ASC , tbl_column ASC

-----------------------

Cast Way
===================================
SELECT 
tbl_column, 
CAST(tbl_column as SIGNED) AS casted_column
FROM db_table
ORDER BY casted_column ASC , tbl_column ASC

MySQLでのNaturalソート

指定の入力

Table: sorting_test
 -------------------------- -------------
| alphanumeric VARCHAR(75) | integer INT |
 -------------------------- -------------
| test1                    | 1           |
| test12                   | 2           |
| test13                   | 3           |
| test2                    | 4           |
| test3                    | 5           |
 -------------------------- -------------

期待される出力

 -------------------------- -------------
| alphanumeric VARCHAR(75) | integer INT |
 -------------------------- -------------
| test1                    | 1           |
| test2                    | 4           |
| test3                    | 5           |
| test12                   | 2           |
| test13                   | 3           |
 -------------------------- -------------

クエリ

SELECT alphanumeric, integer
       FROM sorting_test
       ORDER BY LENGTH(alphanumeric), alphanumeric  

英数字の値を混合した数値のソート

指定の入力

2a, 12, 5b, 5a, 10, 11, 1, 4b

期待される出力

1, 2a, 4b, 5a, 5b, 10, 11, 12

クエリ

SELECT version
FROM version_sorting
ORDER BY CAST(version AS UNSIGNED), version;

お役に立てれば

74
追加された
より完全な情報をこの記事自体に含めることは素晴らしいことです。
追加された 著者 showdev,
@showdev私はそれを含めて、それが役に立つかもしれないことを願っ:)
追加された 著者 affaz,
これらのどれも私のために働いていませんでした:/このようなリストの推奨? pastebin.com/d4kXq6HS 理想的な出力は次のとおりです。 pastebin.com/kJ4Zc3XY
追加された 著者 err,

私はこの投稿が閉鎖されていることを知っているが、私の方法は一部の人々を助けることができると思いだからそこにある:

私のデータセットは非常に似ていますが、もう少し複雑です。数字、英数字データ:

1
2
Chair 
3
0
4
5
-
Table
10
13
19
Windows
99
102
Dog

私は最初に ' - '記号を、その後に数字を、テキストをつけたいと思います。

だから私はこのように行く:

SELECT name, (name = '-') boolDash, (name = '0') boolZero, (name+0 > 0) boolNum 
FROM table 
ORDER BY boolDash DESC, boolZero DESC, boolNum DESC, (name+0), name

結果は何かになるはずです:

-
0    
1
2
3
4
5
10
13
99
102
Chair
Dog
Table
Windows

全体的なアイデアは、SELECTとソートの結果を簡単にチェックすることです。

12
追加された
私はselect文に(name = ' - ')boolDash を入れることで、これを動作させることができませんでした。しかし、私はそれを name = ' - ' をorder byステートメントに直接置くことによって動作させました。
追加された 著者 Yep_It's_Me,

ちょうどこれを行う:

SELECT * FROM table ORDER BY column `name`+0 ASC

+0を追加すると、次のようになります。

0、 図10において、 図11において、 図2において、 図3では、 4

次のようになる:

0、 図2において、 図3では、 図4において、 図10において、 11

10
追加された
@Tarikおそらく推定値である information_schema を使用しているため、完全に集約されていない可能性があります。
追加された 著者 Andrew Odendaal,
数値で始まるchar値に対しては機能しません。
追加された 著者 Blouarf,
これは非常に危険です!私の質問ではうまくいきましたが、私は答えをアップアップしましたが、リフレッシュしたときにうまくいかなかったのです!それから私は先に進んで100回クエリをリフレッシュし、ランダムに動作し、同じクエリに対しては機能しません!これに頼らないでください!私のテーブルには最後に数値があります。SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'my_database' AND TABLE_NAME LIKE '%my_table%' ORDER BY TABLE_NAME + 0 DESC LIMIT 1
追加された 著者 Tarik,
これは、charカラムの数値に対してのみ機能します。
追加された 著者 dbinott,

私はこれが嫌いですが、これが有効です

order by lpad(name, 10, 0)  <-- assuming maximum string length is 10
                            <-- you can adjust to a bigger length if you want to
5
追加された
これは実際に私の USA-0027-1、USA-0027-2、USA-0027-10、USA-0027-12 のシナリオで機能します。
追加された 著者 dbinott,

私は良い結果を出しました

SELECT alphanumeric, integer FROM sorting_test ORDER BY CAST(alphanumeric AS UNSIGNED), alphanumeric ASC
4
追加された

私はあなたの列のデータ型がテキストまたは適切にソートされていない他のものだと思います。 int型、bigint型、浮動小数点型のように変更して、正しく動作するようにしてください...

SELECT * FROM table ORDER BY column name ASC
2
追加された
OPはそれが英数字であると言いました。
追加された 著者 dbinott,

このタイプの質問は以前に尋ねられました。

あなたが話している並べ替えのタイプは、「Natural Sorting」と呼ばれます。 並べ替えを実行するデータは英数字です。 並べ替えのために新しい列を作成する方が良いでしょう。

For further help check natural-sort-in-mysql

1
追加された

関数を記述して SELECT クエリを遅くするのではなく、これを行う別の方法を考えました...

次のクラスの結果を保持するデータベースに余分なフィールドを作成し、新しい行を挿入するときは、このクラスを通して自然にソートされるフィールド値を実行し、その結果を追加フィールドに保存します。その後、元のフィールドで並べ替える代わりに、余分なフィールドで並べ替えます。

String nsFieldVal = new NaturalSortString(getFieldValue()、4).toString()

The above means:
- Create a NaturalSortString for the String returned from getFieldValue()
- Allow up to 4 bytes to store each character or number (4 bytes = ffff = 65535)

| field(32)  |  nsfield(161)                            |   
  a1            300610001

String sortString = new NaturalSortString(getString()、4).toString()

import StringUtils;

/**
 * Creates a string that allows natural sorting in a SQL database
 * eg, 0 1 1a 2 3 3a 10 100 a a1 a1a1 b
 */
public class NaturalSortString {

    private String inStr;
    private int byteSize;
    private StringBuilder out = new StringBuilder();

    /**
     * A byte stores the hex value (0 to f) of a letter or number.
     * Since a letter is two bytes, the minimum byteSize is 2.
     *
     * 2 bytes = 00 - ff  (max number is 255)
     * 3 bytes = 000 - fff (max number is 4095)
     * 4 bytes = 0000 - ffff (max number is 65535)
     *
     * For example:
     * dog123 = 64,6F,67,7B and thus byteSize >= 2.      
     * dog280 = 64,6F,67,118 and thus byteSize >= 3.
     *
     * For example:
     * The String, "There are 1000000 spots on a dalmatian" would require a byteSize that can 
     * store the number '1000000' which in hex is 'f4240' and thus the byteSize must be at least 5
     *
     * The dbColumn size to store the NaturalSortString is calculated as:
     * > originalStringColumnSize x byteSize + 1
     * The extra '1' is a marker for String type - Letter, Number, Symbol
     * Thus, if the originalStringColumn is varchar(32) and the byteSize is 5:
     * > NaturalSortStringColumnSize = 32 x 5 + 1 = varchar(161)
     *
     * The byteSize must be the same for all NaturalSortStrings created in the same table.
     * If you need to change the byteSize (for instance, to accommodate larger numbers), you will
     * need to recalculate the NaturalSortString for each existing row using the new byteSize.
     *
     * @param str        String to create a natural sort string from
     * @param byteSize   Per character storage byte size (minimum 2)
     * @throws Exception See the error description thrown
     */
    public NaturalSortString(String str, int byteSize) throws Exception {
        if (str == null || str.isEmpty()) return;
        this.inStr = str;
        this.byteSize = Math.max(2, byteSize); //minimum of 2 bytes to hold a character
        setStringType();
        iterateString();
    }

    private void setStringType() {
        char firstchar = inStr.toLowerCase().subSequence(0, 1).charAt(0);
        if (Character.isLetter(firstchar))    //letters third
            out.append(3);
        else if (Character.isDigit(firstchar))//numbers second
            out.append(2);
        else                                  //non-alphanumeric first
            out.append(1);
    }

    private void iterateString() throws Exception {
        StringBuilder n = new StringBuilder();
        for (char c : inStr.toLowerCase().toCharArray()) {//lowercase for CASE INSENSITIVE sorting
            if (Character.isDigit(c)) {
               //group numbers
                n.append(c);
                continue;
            }
            if (n.length() > 0) {
                addInteger(n.toString());
                n = new StringBuilder();
            }
            addCharacter(c);
        }
        if (n.length() > 0) {
            addInteger(n.toString());
        }
    }

    private void addInteger(String s) throws Exception {
        int i = Integer.parseInt(s);
        if (i >= (Math.pow(16, byteSize)))
            throw new Exception("naturalsort_bytesize_exceeded");
        out.append(StringUtils.padLeft(Integer.toHexString(i), byteSize));
    }

    private void addCharacter(char c) {
        //TODO: Add rest of accented characters
        if (c >= 224 && c <= 229)//set accented a to a
            c = 'a';
        else if (c >= 232 && c <= 235)//set accented e to e
            c = 'e';
        else if (c >= 236 && c <= 239)//set accented i to i
            c = 'i';
        else if (c >= 242 && c <= 246)//set accented o to o
            c = 'o';
        else if (c >= 249 && c <= 252)//set accented u to u
            c = 'u';
        else if (c >= 253 && c <= 255)//set accented y to y
            c = 'y';

        out.append(StringUtils.padLeft(Integer.toHexString(c), byteSize));
    }

    @Override
    public String toString() {
        return out.toString();
    }
}

完全性のために、以下は StringUtils.padLeft メソッドです:

public static String padLeft(String s, int n) {
    if (n - s.length() == 0) return s;
    return String.format("%0" + (n - s.length()) + "d%s", 0, s);
}

結果は次のようになるはずです

-1
-a
0
1
1.0
1.01
1.1.1
1a
1b
9
10
10a
10ab
11
12
12abcd
100
a
a1a1
a1a2
a-1
a-2
áviacion
b
c1
c2
c12
c100
d
d1.1.1
e
0
追加された

標準フォーマットのない英数字列をソートする必要がある場合

SELECT * FROM table ORDER BY (name = '0') DESC, (name+0 > 0) DESC, name+0 ASC, name ASC

追加のロジックを使用して、必要に応じてこの文字列に英数字以外の文字を含めることができます。

0
追加された

これは、データの種類に対して有効です。    Data1、 Data2、Data3 ...... ......、Data21となる。意味 "データ"文字列はすべての行で共通です。

ORDER BY ASCでは完全にソートされますが、ORDER BY DESCは適切ではありません。

SELECT * FROM table_name ORDER BY LENGTH(column_name), column_name ASC;
0
追加された

これは英数字フィールドを次のようにソートする必要があります: 1 /数字のみ、 1,2,3,4,5,6,7,8,9,10,11 などによる注文 2 /次に、 1foo、2bar、aaa11aa、aaa22aa、b5452 などのテキストを含むフィールド

SELECT  MyField
FROM MyTable
order by 
    IF( MyField REGEXP '^-?[0-9]+$' = 0, 
    9999999999 ,  
    CAST(MyField AS DECIMAL) 
    ), MyField

クエリがデータであるかどうかをチェックし、9999999999に入力していない場合は、最初にこの列を注文し、次にテキスト付きのデータを注文します

がんばろう!

0
追加された

セレクト s.id、s.name、LENGTH(s.name)len、ASCII(s.name)ASCCCI FROM table_name s ORDER BY ASCCCI、len、NAME ASC;

0
追加された