3

私たちのアプリケーションにはCustomerNumberフィールドがあります。何百人もの人々がシステムを使用しています (それぞれが独自のログインと独自の のリストを持っていますCustomerNumber)。個々のユーザーは、最大で 100,000 人の顧客を持つことができます。多くは100未満です。

顧客番号フィールドに実際の数字のみを入力する人もいれば、それらを組み合わせて使用​​する人もいます。システムでは、A ~ Z、0 ~ 9、またはダッシュの 20 文字を使用でき、これらを VARCHAR2(20) に格納します。小文字は格納される前に大文字に変換されます。

ここで、特定のユーザーのすべての顧客を顧客番号で並べ替えて一覧表示する簡単なレポートがあるとします。例えば

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

これは単純な解決策です。数値しか使用しない人は、単純なアルファベット順 (「9」の前に「10」が来る) を見たくないからです。

ユーザーのデータについて不必要な質問をしたくありません。

私は Oracle を使用していますが、他のデータベースのソリューションも見られると興味深いと思います。回答がどのデータベースで機能するかを含めてください。

これを実装する最良の方法は何だと思いますか?

4

5 に答える 5

4

おそらく最善の策は、別の列を事前に計算し、それを注文に使用し、顧客番号を表示に使用することです。これにはおそらく、内部整数を固定長に 0 でパディングする必要があります。

もう 1 つの可能性は、返された結果に対してソート後選択を行うことです。

Jeff Atwood は、一部の人々が人間に優しい並べ替え順序を計算する方法についてのブログ投稿をまとめました。

于 2009-02-16T02:55:51.787 に答える
2

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

これは、位置ではなく、最初に出現した番号で並べ替えられます。つまり、次のようになります。

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

、ここで、?は順序が未定義であることを意味します。

ほとんどの場合、これで十分です。

大文字と小文字を区別するために、リストの時間に2を追加しREGEXP_INSTR(cust_name, '[0-9]', n)て、数字の-番目(など)のグループの最初の出現に順序を強制することができます。ORDER BYnn2nd3rd

ケースに並べ替え順序を強制するには、リスト時間に3を追加しTO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+', n))て、 -番目の順序を強制します。数字のグループ。ORDER BYnn

実際には、私が書いたクエリで十分です。

これらの式に基づいて関数ベースのインデックスを作成することもできますが、ヒントを使用して強制する必要があります。関数ベースのインデックスを信頼できないためSORT ORDER BY、とにかくワンパスが実行されます。CBOORDER BY

于 2009-02-16T12:01:06.610 に答える
1

私は同様の恐ろしい状況にあり、それに対処するために適切に恐ろしい機能を開発しました(SQLServer)

私の状況では、「単位」の表があります (これは学生のための作業追跡システムであるため、このコンテキストでの単位は学生が行っているコースを表します)。ユニットにはコードがあり、ほとんどの場合純粋な数値ですが、さまざまな理由で varchar になり、最大 5 文字のプレフィックスを付けることを決定しました。したがって、53,123,237,356 が正常にソートされることを期待していますが、T53、T123、T237、T356 もソートされると予想されます。

UnitCode は nvarchar(30) です

関数の本体は次のとおりです。

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

それを書いた後、私は自分の顔を撃ちたかったのですが、それは機能し、実行時にサーバーを殺さないようです.

于 2009-02-16T23:51:04.640 に答える
1

CustomerNumber が純粋な数値 (それ以外の場合は NULL [1]) の場合にのみ使用される数値列 [CustomerNumberInt] を持つことができます。

ORDER BY CustomerNumberInt, CustomerNumber

[1] SQL バージョンが ORDER BY の NULL をどのように処理するかによって、デフォルトをゼロ (または無限!) にしたい場合があります。

于 2009-02-16T12:15:24.703 に答える