SQL para ordenar por número - 1,2,3,4 etc em vez de 1,10,11,12

86

Estou tentando ordenar por uma coluna de número em meu banco de dados que tem valores 1-999

Quando eu uso

ORDER_BY registration_no ASC

Eu recebo….

1
101
102
103
104
105
106
107
108
109
11
110
Etc…

Portanto, parece estar ordenando pelo primeiro dígito em oposição ao número.

Alguém sabe qual SQL usar se quiser ordenar por valor? Então 1,2,3,4,5,6etc

Konnor262
fonte
11
Sua coluna é do tipo varchar por causa do qual você está enfrentando esse comportamento.
Meherzad
qual é o tipo de dados da coluna registration_no?
Praveen Prasannan
9
Use order by registration_no + 0 ascpara resolver seu problema.
Meherzad
10
Você nunca deve armazenar números em uma coluna de caracteres. Seu problema é resultado direto desse erro.
a_horse_with_no_name
Minha coluna é Varchar e os dados que armazeno são Classe 10 / Classe 9 / Classe 8. Agora, a classe 10 vem antes da classe 8. Como faço para resolver isso sem ter que fazer em uma coluna display_order?
Vishnoo Rath

Respostas:

139

Uma maneira de ordenar por números inteiros positivos, quando eles são armazenados como varchar, é ordenar primeiro pelo comprimento e depois pelo valor:

order by len(registration_no), registration_no

Isso é particularmente útil quando a coluna pode conter valores não numéricos.

Nota: em alguns bancos de dados, a função para obter o comprimento de uma string pode ser chamada em length()vez de len().

Gordon Linoff
fonte
1
Isso não funcionará em todos os casos. Em princípio, os casos que não funcionam são misturas de números inteiros com; números negativos, números com zeros à esquerda, números com frações e palavras e números combinados.
WonderWorker de
10
@ Knickerless-Noggins. . . Leia a primeira frase da resposta. Acho que está bem claro.
Gordon Linoff
@GordonLinoff está ordenando pela mesma coluna duas vezes não usa CPU e memória intensiva?
loneStar
@Achyuth. . . O número de chaves em um order bytem pouco efeito no desempenho.
Gordon Linoff
1
Para Oracle SQL, use em length()vez delen()
Stevoisiak
61
ORDER_BY cast(registration_no as unsigned) ASC

converte explicitamente o valor em um número. Outra possibilidade de conseguir o mesmo seria

ORDER_BY registration_no + 0 ASC

o que forçará uma conversa implícita.

Na verdade, você deve verificar a definição da tabela e alterá-la. Você pode alterar o tipo de dados para intassim

ALTER TABLE your_table MODIFY COLUMN registration_no int;
Juergen d
fonte
13

Se você estiver usando o SQL Server:

ORDER_BY cast(registration_no as int) ASC
IPOSTEDONCE
fonte
3
ORDER_BY cast(registration_no as unsigned) ASC

dá o resultado desejado com avisos.

Portanto, é melhor ir para

ORDER_BY registration_no + 0 ASC

para um resultado limpo sem nenhum aviso SQL.

Priyanka
fonte
2

Presumo que seu tipo de coluna seja STRING (CHAR, VARCHAR, etc) e o procedimento de classificação é classificá-lo como uma string. O que você precisa fazer é converter o valor em valor numérico. Como fazer isso dependerá do sistema SQL que você usa.


fonte
1

Às vezes, você simplesmente não tem a opção de armazenar números misturados com texto. Em um de nossos aplicativos, o host do site que usamos para nosso site de comércio eletrônico cria filtros dinamicamente fora das listas. Não há opção de classificar por qualquer campo, exceto pelo texto exibido. Quando queríamos filtros construídos a partir de uma lista que dizia coisas como 2 "a 8" 9 "a 12" 13 "a 15" etc., precisávamos classificar 2-9-13, não 13-2-9 como acontecerá quando lendo os valores numéricos. Portanto, usei a função Replicar do SQL Server junto com o comprimento do número mais longo para preencher quaisquer números mais curtos com um espaço à esquerda. Agora, 20 é classificado após 3 e assim por diante.

Eu estava trabalhando com uma visão que me dava os comprimentos, larguras, etc. mínimos e máximos para o tipo de item e classe, e aqui está um exemplo de como fiz o texto. (LB n Low e LB n High são as extremidades inferior e superior dos 5 suportes de comprimento.)

REPLICATE(' ', LEN(LB5Low) - LEN(LB1High)) + CONVERT(NVARCHAR(4), LB1High) + '" and Under' AS L1Text,
REPLICATE(' ', LEN(LB5Low) - LEN(LB2Low)) + CONVERT(NVARCHAR(4), LB2Low) + '" to ' + CONVERT(NVARCHAR(4), LB2High) + '"' AS L2Text,
REPLICATE(' ', LEN(LB5Low) - LEN(LB3Low)) + CONVERT(NVARCHAR(4), LB3Low) + '" to ' + CONVERT(NVARCHAR(4), LB3High) + '"' AS L3Text,
REPLICATE(' ', LEN(LB5Low) - LEN(LB4Low)) + CONVERT(NVARCHAR(4), LB4Low) + '" to ' + CONVERT(NVARCHAR(4), LB4High) + '"' AS L4Text,
CONVERT(NVARCHAR(4), LB5Low) + '" and Over' AS L5Text
Joey Morgan
fonte
1

Prefiro fazer um “PAD” nos dados. O MySql o chama de LPAD, mas você pode trabalhar para fazer a mesma coisa no SQL Server.

ORDER BY  REPLACE(STR(ColName, 3), SPACE(1), '0') 

Esta fórmula fornecerá zeros à esquerda com base no comprimento da coluna de 3. Essa funcionalidade é muito útil em outras situações fora de ORDER BY, por isso eu queria fornecer essa opção.

Resultados: 1 torna-se 001 e 10 torna-se 010, enquanto 100 permanece o mesmo.

SQLCodingIsFunnn
fonte
0

Este problema ocorre porque você declarou a coluna no tipo de dados CHAR, VARCHAR ou TEXT. Basta alterar o tipo de dados para INT, BIGINT etc. Isso resolverá o problema de seu pedido personalizado.

Dev Rathi
fonte