J'ai une colonne VARCHAR
dans un SQL Server 2000
base de données pouvant contenir des lettres ou des chiffres. Cela dépend de la configuration de l'application sur le front-end pour le client.
Lorsqu'il contient des chiffres, je veux qu'il soit trié numériquement, par exemple comme "1", "2", "10" au lieu de "1", "10", "2". Les champs contenant uniquement des lettres ou des lettres et des chiffres (tels que "A1") peuvent être triés par ordre alphabétique comme d'habitude. Par exemple, ce serait un ordre de tri acceptable.
1
2
10
A
B
B1
Quelle est la meilleure façon d'y parvenir?
Une solution possible consiste à remplir les valeurs numériques avec un caractère devant afin que toutes aient la même longueur de chaîne.
Voici un exemple utilisant cette approche:
select MyColumn
from MyTable
order by
case IsNumeric(MyColumn)
when 1 then Replicate('0', 100 - Len(MyColumn)) + MyColumn
else MyColumn
end
Le 100
doit être remplacé par la longueur réelle de cette colonne.
Il existe plusieurs façons de procéder.
L'une serait
SELECT
...
ORDER BY
CASE
WHEN ISNUMERIC(value) = 1 THEN CONVERT(INT, value)
ELSE 9999999 -- or something huge
END,
value
la première partie de ORDER BY convertit tout en entier (avec une valeur énorme pour les non-numériques, pour trier en dernier) puis la dernière partie s'occupe de l'alphabet.
Notez que les performances de cette requête sont probablement au moins modérément horribles sur de grandes quantités de données.
SELECT *, CONVERT(int, your_column) AS your_column_int
FROM your_table
ORDER BY your_column_int
OU
SELECT *, CAST(your_column AS int) AS your_column_int
FROM your_table
ORDER BY your_column_int
Les deux sont assez portables je pense.
select
Field1, Field2...
from
Table1
order by
isnumeric(Field1) desc,
case when isnumeric(Field1) = 1 then cast(Field1 as int) else null end,
Field1
Cela renverra les valeurs dans l'ordre que vous avez donné dans votre question.
Les performances ne seront pas trop bonnes avec tout ce casting, donc une autre approche consiste à ajouter une autre colonne à la table dans laquelle vous stockez une copie entière des données, puis triez en fonction de celle-ci en premier, puis de la colonne en question. Cela nécessitera évidemment quelques modifications de la logique qui insère ou met à jour les données dans la table, pour remplir les deux colonnes. Soit cela, soit placez un déclencheur sur la table pour remplir la deuxième colonne chaque fois que des données sont insérées ou mises à jour.
vous pouvez toujours convertir votre colonne varchar en bigint car l'entier peut être trop court ...
select cast([yourvarchar] as BIGINT)
mais vous devez toujours vous soucier des caractères alpha
where ISNUMERIC([yourvarchar] +'e0') = 1
le + 'e0' vient de http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/isnumeric-isint-isnumber
cela conduirait à votre déclaration
SELECT
*
FROM
Table
ORDER BY
ISNUMERIC([yourvarchar] +'e0') DESC
, LEN([yourvarchar]) ASC
la première colonne de tri mettra le numérique en haut. le second trie par longueur, donc 10 précédera 0001 (ce qui est stupide?!)
cela conduit à la deuxième version:
SELECT
*
FROM
Table
ORDER BY
ISNUMERIC([yourvarchar] +'e0') DESC
, RIGHT('00000000000000000000'+[yourvarchar], 20) ASC
la deuxième colonne est maintenant complétée à droite par '0', donc le tri naturel met les entiers avec des zéros en tête (0,01,10,0100 ...) dans le bon ordre (correct!) - mais tous les alphas seraient améliorés avec '0' -chars (performance)
donc troisième version:
SELECT
*
FROM
Table
ORDER BY
ISNUMERIC([yourvarchar] +'e0') DESC
, CASE WHEN ISNUMERIC([yourvarchar] +'e0') = 1
THEN RIGHT('00000000000000000000' + [yourvarchar], 20) ASC
ELSE LTRIM(RTRIM([yourvarchar]))
END ASC
maintenant, les chiffres sont d'abord remplis de caractères `` 0 '' (bien sûr, la longueur 20 pourrait être améliorée) - ce qui trie les chiffres correctement - et les alphas ne sont coupés
Je l'ai résolu de manière très simple en écrivant ceci dans la partie "commande"
ORDER BY (
sr.codice +0
)
ASC
Cela semble très bien fonctionner, en fait j'ai eu le tri suivant:
16079 Customer X
016082 Customer Y
16413 Customer Z
Alors le 0
en face de 16082
est considéré correctement.
Cela semble fonctionner:
select your_column
from your_table
order by
case when isnumeric(your_column) = 1 then your_column else 999999999 end,
your_column
Cette requête vous est utile. Dans cette requête, une colonne a le type de données varchar est organisée par bon ordre. Par exemple - Dans cette colonne, les données sont: - G1, G34, G10, G3. Ainsi, après avoir exécuté cette requête, vous voyez les résultats: - G1, G10, G3, G34.
SELECT *,
(CASE WHEN ISNUMERIC(column_name) = 1 THEN 0 ELSE 1 END) IsNum
FROM table_name
ORDER BY IsNum, LEN(column_name), column_name;
Cela peut vous aider, j'ai essayé cela lorsque j'ai eu le même problème.
SELECT * FROM tab ORDER BY IIF(TRY_CAST(val AS INT) IS NULL, 1, 0),TRY_CAST(val AS INT);
SELECT FIELD FROM TABLE
ORDER BY
isnumeric(FIELD) desc,
CASE ISNUMERIC(test)
WHEN 1 THEN CAST(CAST(test AS MONEY) AS INT)
ELSE NULL
END,
FIELD
Selon ce lien vous devez effectuer un cast vers MONEY puis INT pour éviter de commander '$' en nombre.