2016-10-18 1 views
2

Je traite des valeurs de colonnes alphanumériques qui doivent être triées par des lettres et ensuite par des nombres.SQL Alphanumeric Tri sur la colonne VARCHAR

Exemple de données:

  • a1
  • a10 a11
  • AB2
  • AB21
  • ab22
  • A1A
  • A1B

a besoin d'être triés comme suit:

  • a1
  • A1A
  • A1B
  • a2
  • a3
  • AB1
  • AB2
  • AB3
  • ...

Besoin de conseils sur la façon de régler ce problème dans SQL.

Merci.

+1

est le format de chaîne cohérent? aussi quel est le dbms utilisé? –

+0

Pas exactement, la partie numérique est précédée de 1-3 lettres. – AlexVPerl

+0

Veuillez marquer votre question avec la base de données que vous utilisez. –

Répondre

0

Vous avez essayé?

SELECT column_x 
FROM table_name x 
ORDER BY x.column_name ASC|DESC, x.column_name ASC|DESC; 
1

Ce qui suit peut fonctionner pour les alphanumériques. Cependant, soyez averti que le comportement n'est pas défini pour les valeurs non alphanumériques.

WITH A (A, N) AS (
    SELECT A, 3 + LEN(A) FROM (
     SELECT 'a1' 
     UNION ALL 
     SELECT 'a10' 
     UNION ALL 
     SELECT 'a11' 
     UNION ALL 
     SELECT 'ab2' 
     UNION ALL 
     SELECT 'ab21' 
     UNION ALL 
     SELECT 'ab22' 
     UNION ALL 
     SELECT 'a1a' 
     UNION ALL 
     SELECT 'a1b' 
     UNION ALL 
     SELECT 'a1' 
     UNION ALL 
     SELECT 'a1a' 
     UNION ALL 
     SELECT 'a1b' 
     UNION ALL 
     SELECT 'a2' 
     UNION ALL 
     SELECT 'a3' 
     UNION ALL 
     SELECT 'a9' 
     UNION ALL 
     SELECT 'ab1' 
     UNION ALL 
     SELECT 'ab2' 
     UNION ALL 
     SELECT 'ab3' 
    ) T (A) 
), B (A, N, I, C, D, X) AS (
    SELECT A, N, 3, CAST(SUBSTRING(A, 1, 1) AS VARCHAR(255)), CAST(SUBSTRING(A, 2, 1) AS VARCHAR(255)), CAST('' AS VARCHAR(255)) FROM A 
    UNION ALL 
    SELECT A, N, I + 1, D, CAST(SUBSTRING(A, I, 1) AS VARCHAR(255)), CASE WHEN ASCII(C) BETWEEN 48 AND 57 AND ASCII(D) BETWEEN 48 AND 57 THEN CAST(X + CHAR(10 + ASCII(D)) AS VARCHAR(255)) WHEN 58 > ASCII(C) THEN CAST(X + C AS VARCHAR(255)) ELSE CAST(X + CHAR(3 + ASCII(C)) AS VARCHAR(255)) END FROM B WHERE I <= N 
) 
SELECT A FROM B WHERE I = N 
ORDER BY X COLLATE Latin1_General_BIN 

Le code trie actuellement en cas de manière sensible, mais il peut être modifié pour faire une affaire sorte insensible aussi bien, par exemple en utilisant

ORDER BY UPPER(X) COLLATE Latin1_General_BIN 

ou

ORDER BY LOWER(X) COLLATE Latin1_General_BIN