Comment trier et afficher des listes mixtes de alphas et les chiffres que les utilisateurs attendent?

StackOverflow https://stackoverflow.com/questions/552053

Question

Notre application a un champ de CustomerNumber. Nous avons des centaines de personnes différentes en utilisant le système (chacun a leur propre login et leur propre liste de CustomerNumbers). Un utilisateur peut avoir au plus 100.000 clients. Beaucoup ont moins de 100.

Certaines personnes ne mettent que les chiffres réels dans leurs champs de numéro de client, tandis que d'autres utilisent un mélange de choses. Le système permet 20 caractères qui peuvent être A-Z, 0-9 ou un tableau de bord, et les stocke dans un VARCHAR2 (20). minuscule Tout est fait en majuscules avant d'être stockées.

Maintenant, disons que nous avons un rapport simple qui répertorie tous les clients pour un utilisateur particulier, trié par numéro de client. par exemple.

SELECT CustomerNumber,CustomerName
FROM Customer
WHERE User = ?
ORDER BY CustomerNumber;

Ceci est une solution naïve que les gens qui ne jamais utilisent les chiffres ne veulent pas voir une sorte alphabétique plaine (où « 10 » vient avant « 9 »).

Je ne veux pas demander à l'utilisateur des questions inutiles au sujet de leurs données.

J'utilise Oracle, mais je pense qu'il serait intéressant de voir des solutions pour d'autres bases de données. S'il vous plaît inclure quelle base de données sur votre réponse fonctionne.

Que pensez-vous de la meilleure façon de mettre en œuvre c'est?

Était-ce utile?

La solution

Dans Oracle 10g:

SELECT  cust_name
FROM    t_customer c 
ORDER BY
    REGEXP_REPLACE(cust_name, '[0-9]', ''), TO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+'))

triera par la première occurence du nombre, pas en ce qui concerne sa position, i. e.

  1. customer1 < customer2 < customer10
    • cust1omer ? customer1
    • cust8omer1 ? cust8omer2

, où un ? signifie que l'ordre est indéfini.

Cela suffit pour la plupart des cas.

Pour forcer l'ordre de tri sur 2 cas, vous pouvez ajouter un REGEXP_INSTR(cust_name, '[0-9]', n) à ORDER BY fois la liste de n, forçant l'ordre sur la première apparition de n-ème (2nd, 3rd etc.) groupe de chiffres.

Pour forcer l'ordre de tri sur 3 cas, vous pouvez ajouter un TO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+', n)) à ORDER BY fois la liste de n, forçant ordre de n-ème. groupe de chiffres.

Dans la pratique, la requête que j'ai écrit est assez.

Vous pouvez créer une fonction index à partir de ces expressions, mais vous aurez besoin de la forcer avec un soupçon et une SORT ORDER BY une passe sera réalisée de toute façon, comme CBO ne fait pas confiance assez index-base de fonction permettre une ORDER BY sur eux.

Autres conseils

Probablement votre meilleur pari est de pré-calculer une colonne séparée et l'utiliser pour commander et utiliser le numéro de client pour l'affichage. Cela impliquerait probablement 0 padding tout entiers internes à une longueur fixe.

L'autre possibilité est de faire le tri après sélection sur les résultats retournés.

a mis en place un affichage blog sur la façon dont certaines personnes calculer les ordres de tri très conviviales.

Vous pourriez avoir une colonne numérique [CustomerNumberInt] qui est utilisé uniquement lorsque le CustomerNumber est purement numérique (NULL sinon [1]), puis

ORDER BY CustomerNumberInt, CustomerNumber

[1] en fonction de comment votre version SQL NULLs ORDER BY vous voudrez peut-être par défaut à zéro (ou l'infini!)

J'ai une situation horrible similaire et ont développé une fonction appropriée horribles pour y faire face (SQLServer)

Dans ma situation, j'ai une table des « unités » (ce qui est un système de suivi des travaux pour les étudiants, si l'unité dans ce contexte représente un cours qu'ils font). Les unités ont un code, qui pour la plupart est purement numérique, mais pour diverses raisons, il a été fait un varchar et ils ont décidé de préfixer certains jusqu'à 5 caractères. Alors, ils attendent 53123237356 pour trier normalement, mais aussi T53, T123, T237, T356

UnitCode est un nvarchar (30)

Voici le corps de la fonction:

declare @sortkey nvarchar(30)

select @sortkey = 
    case
        when @unitcode like '[^0-9][0-9]%' then left(@unitcode,1) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-1)
        when @unitcode like '[^0-9][^0-9][0-9]%' then left(@unitcode,2) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-2)
        when @unitcode like '[^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,3) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-3)
        when @unitcode like '[^0-9][^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,4) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-4)
        when @unitcode like '[^0-9][^0-9][^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,5) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-5)
        when @unitcode like '%[^0-9]%' then @unitcode
        else left('000000000000000000000000000000',30-len(@unitcode)) + @unitcode
    end 

return @sortkey

Je voulais me tirer une balle dans le visage après avoir écrit que, mais il fonctionne et semble ne pas tuer le serveur quand il fonctionne.

J'ai utilisé ce dans SQL Server et fonctionne très bien: Voici la solution consiste à rembourrer les valeurs numériques avec un caractère en avant pour que tous sont de la même longueur de chaîne

.

Voici un exemple en utilisant cette approche:

select MyCol
from MyTable
order by 
    case IsNumeric(MyCol) 
        when 1 then Replicate('0', 100 - Len(MyCol)) + MyCol
        else MyCol
    end

100 doit être remplacé par la longueur réelle de cette colonne.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top