it-swarm-pt.tech

MySQL 'Order By' - ordenação alfanumérica corretamente

Eu quero classificar os seguintes itens de dados na ordem em que são apresentados abaixo (números 1-12):

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

No entanto, minha consulta - usando order by xxxxx asc classifica pelo primeiro dígito acima de tudo:

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

Algum truque para fazer isso mais corretamente?

Além disso, no interesse da divulgação completa, isso poderia ser uma mistura de letras e números (embora neste momento não seja), por exemplo:

 A1 
 534G 
 G46A 
 100B 
 100A 
 100JE 

etc ....

Obrigado!

update: pessoas pedindo consulta

select * from table order by name asc
49
Shackrock

As pessoas usam truques diferentes para fazer isso. Eu pesquisei e descobri alguns resultados, cada um seguindo diferentes truques. Dê uma olhada neles:

Editar:

Acabei de adicionar o código de cada link para futuros visitantes.

Ordenação alfabética numérica no MySQL

Given input

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

Saída esperada

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

Ordenação Natural no MySQL

Given input

Tabela: sorting_test 
 -------------------------- ------------- 
 | VARCHAR alfanumérico (75) | inteiro INT | 
 -------------------------- ------------- 
 | test1 | 1 | 
 | test12 | 2 | 
 | test13 | 3 | 
 | test2 | 4 | 
 | test3 | 5 | 
 -------------------------- ------------- 

Saída esperada

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

Inquerir

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

Classificando valores numéricos misturados com valores alfanuméricos

Given input

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

Saída esperada

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

Inquerir

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

Espero que isto ajude

83
Jomoos

Eu sei que este post está fechado, mas acho que meu jeito pode ajudar algumas pessoas. Então é isso:

Meu conjunto de dados é muito semelhante, mas é um pouco mais complexo. Tem números, dados alfanuméricos:

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

Eu gostaria de ter o símbolo '-' primeiro, depois os números e depois o texto.

Então eu vou assim:

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

O resultado deve ser algo:

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

A ideia é fazer uma verificação simples no SELECT e classificar com o resultado.

13
antoine

Apenas faça isso:

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

Acrescentar o +0 significa que:

0, 10, 11, 2, 3, 4

torna-se :

0, 2, 3, 4, 10, 11

10
Andrew Odendaal

Eu odeio isso, mas isso vai funcionar

order by lpad(name, 10, 0)  <-- assuming maximum string length is 10
                            <-- you can adjust to a bigger length if you want to
7
ajreal

Eu tive alguns bons resultados com 

SELECT alphanumeric, integer FROM sorting_test ORDER BY CAST(alphanumeric AS UNSIGNED), alphanumeric ASC
4
Blouarf

Esse tipo de pergunta foi perguntado anteriormente.

O tipo de classificação sobre o qual você está falando é chamado de "Classificação Natural". Os dados que você deseja classificar são alfanuméricos. Seria melhor criar uma nova coluna para classificação.

Para mais ajuda, verifique natural-sort-in-mysql

1
nishantagarwal

Isso deve classificar o campo alfanumérico como: 1/Number only, order by 1,2,3,4,5,6,7,8,9,10,11 etc ... 2/Então campo com texto como: 1foo, 2bar, aaa11aa, aaa22aa, b5452 etc ...

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

A consulta verifica se os dados são um número, se não for colocado em 9999999999, faça o pedido primeiro nesta coluna e, em seguida, ordene os dados com texto

Boa sorte!

0
user8255718

SELECT S.id, s.name, LENGTH (s.name) len, ASCII (s.name) ASCCCI FROM nome_da_tabela s ORDEM POR ASCCCI, len, NOME ASC ;

0
Hosain Ahmed

Se você precisar classificar uma coluna alfanumérica que não tenha nenhum formato padrão

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

Você pode adaptar essa solução para incluir suporte para caracteres não alfanuméricos, se desejado, usando lógica adicional.

0
Weston Ganger

Isso funciona para tipos de dados: Dados1, Dados2, Dados3 ......, Dados21. Significa "Data" String é comum em todas as linhas. 

Para ORDER BY ASC, ele será classificado perfeitamente, pois ORDER BY DESC não é adequado.

SELECT * FROM table_name ORDER BY LENGTH(column_name), column_name ASC;
0
ShivBuyya

Em vez de tentar escrever alguma função e diminuir a consulta SELECT, pensei em outra maneira de fazer isso ...

Crie um campo extra em seu banco de dados que contenha o resultado da Classe seguinte e, ao inserir uma nova linha, execute o valor do campo que será classificado naturalmente por essa classe e salve seu resultado no campo extra. Então, em vez de classificar por seu campo original, classifique pelo campo extra.

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();
    }
}

Para completar, abaixo está o método 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);
}

O resultado deve sair como o seguinte

-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
Christian