Wie zu sortieren und gemischte Listen von Alphas und Zahlen angezeigt werden, da die Nutzer erwarten?

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

Frage

Unsere Anwendung hat eine CustomerNumber Feld. Wir haben Hunderte von verschiedenen Personen mit dem System (jeder hat seine eigene Login und ihre eigene Liste von CustomerNumbers). Ein einzelner Benutzer kann höchstens 100.000 Kunden. Viele haben weniger als 100.

nur Einige Leute tatsächliche Zahlen setzen in ihre Kundennummer Felder, während andere eine Mischung aus Dingen verwenden. Das System ermöglicht es, die 20 Zeichen von A-Z sein kann, 0-9, oder ein Strich, und speichert diese in einem VARCHAR2 (20). Alles, was Kleingroß gemacht wird, bevor gespeichert werden.

Nun lassen Sie uns sagen, dass wir einen einfachen Bericht haben, die alle Kunden für einen bestimmten Benutzer auflistet, durch Kundennummer sortiert. z.

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

Dies ist eine naive Lösung, wie die Menschen, die je nur Zahlen verwenden wollen nicht eine einfache alphabetische Sortierung sehen (wobei „10“ kommt vor „9“).

Ich mag nicht den Benutzer keine unnötigen Fragen über ihre Daten fragen.

Ich bin mit Oracle, aber ich denke, es wäre interessant, einige Lösungen für andere Datenbanken zu sehen. Bitte geben Sie die Datenbank, um Ihre Antwort arbeitet an.

Was denken Sie, der beste Weg, dies zu realisieren ist?

War es hilfreich?

Lösung

In 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]+'))

Dies wird durch das erste Auftreten von Zahl sortieren, nicht in Bezug auf sie Position ist, i. e.

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

, wobei ein ? bedeutet, dass die Reihenfolge nicht definiert ist.

Das reicht für die meisten Fälle.

Um Sortierreihenfolge auf Fall 2 zwingen Sie ein REGEXP_INSTR(cust_name, '[0-9]', n) kostenlos in der Liste ORDER BY mal n, zwingt, um auf dem ersten Auftreten von n-ten (2nd, 3rd etc.) Zifferngruppe.

Um Sortierreihenfolge auf Fall 3 zu zwingen, können Sie eine TO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+', n)) hinzufügen Liste ORDER BY mal n und zwingt Reihenfolge der n-ten. Zifferngruppe.

In der Praxis ist die Abfrage, die ich geschrieben habe, ist genug.

Sie können eine Funktion basierenden Index auf diesem Ausdrücken erstellen, aber Sie werden es mit einem Hauch zwingen müssen, und eine One-Pass SORT ORDER BY ohnehin durchgeführt werden, da die CBO nicht funktionsBasisIndizes genug vertraut zu erlauben eine ORDER BY auf sie.

Andere Tipps

Wahrscheinlich die beste Wahl ist, um eine separate Spalte vorab zu berechnen und zu verwenden, die für die Bestellung und die Kundennummer für die Anzeige verwenden. Dies würde wahrscheinlich bedeuten 0-padding alle internen Zahlen auf eine feste Länge.

Die andere Möglichkeit ist Ihre Sortier Post-select auf den zurückgegebenen Ergebnissen zu tun.

Jeff Atwood hat zusammen ein Blog-Posting darüber, wie berechnen einige Leute menschliche freundliche Sortierungen.

Sie können eine numerische Spalte [CustomerNumberInt], dass nur verwendet, wenn die Kundennummer rein numerisch ist (NULL ansonsten [1]), dann

ORDER BY CustomerNumberInt, CustomerNumber

[1] je nachdem, wie Sie Ihre SQL-Version behandelt NULL-Werte in ORDER BY Sie ihn auf Null auf Standard möchten (oder unendlich!)

Ich habe eine ähnliche schreckliche Situation und haben eine entsprechend schreckliche Funktion mit ihr umgehen (SQLServer)

entwickelt

In meiner Situation habe ich eine Tabelle von „Einheiten“ (dies ist ein Work-Tracking-System für Studenten, so Einheit in diesem Zusammenhang stellt einen Kurs sie tun). Einheiten haben einen Code, der zum größten Teil rein numerisch ist, aber aus verschiedenen Gründen war es ein varchar gemacht und sie beschlossen, einige von bis zu 5 Zeichen Präfix. So erwarten sie 53123237356 normalerweise zu sortieren, sondern auch T53, T123, T237, T356

Unitcode ist ein nvarchar (30)

Hier ist der Körper der Funktion:

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

Ich wollte mich ins Gesicht schießen nach dem Schreiben, dass, aber es funktioniert und scheint nicht auf den Server zu töten, wenn es ausgeführt wird.

habe ich dies in SQL Server und Arbeiten groß: Hier ist die Lösung der numerischen Werte mit einem Zeichen vor aufzufüllen, so dass alle sind von der gleichen Stringlänge

.

Hier ist ein Beispiel mit diesem Ansatz:

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

Die 100 sollte mit der tatsächlichen Länge der Spalte ersetzt werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top