web-dev-qa-db-ja.com

数値を含むSQLサーバーでVARCHAR列をソートするにはどうすればよいですか?

SQL Server 2000データベースにVARCHAR列があり、文字または数字を含めることができます。これは、顧客のフロントエンドでアプリケーションがどのように構成されているかによって異なります。

数値が含まれている場合は、数値でソートする必要があります。 「1」、「10」、「2」の代わりに「1」、「2」、「10」として。文字のみ、または文字と数字(「A1」など)を含むフィールドは、通常どおりアルファベット順にソートできます。たとえば、これは許容可能なソート順です。

1
2
10
A
B
B1

これを達成する最良の方法は何ですか?

49
Tim C

考えられる解決策の1つは、すべての文字列の長さが同じになるように、数値の前に文字を埋め込むことです。

そのアプローチを使用した例を次に示します。

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

100は、その列の実際の長さに置き換える必要があります。

74
Aleris

これを行うには、いくつかの可能な方法があります。

一つは

SELECT
 ...
ORDER BY
  CASE 
    WHEN ISNUMERIC(value) = 1 THEN CONVERT(INT, value) 
    ELSE 9999999 -- or something huge
  END,
  value

oRDER BYの最初の部分はすべてをintに変換し(最後に並べ替えるために非数値の巨大な値を使用)、最後の部分はアルファベットを処理します。

このクエリのパフォーマンスは、おそらく大量のデータに対して少なくとも中程度に恐ろしいことに注意してください。

12
Cowan
SELECT *, CONVERT(int, your_column) AS your_column_int
FROM your_table
ORDER BY your_column_int

[〜#〜] or [〜#〜]

SELECT *, CAST(your_column AS int) AS your_column_int
FROM your_table
ORDER BY your_column_int

どちらもかなり移植性があると思います。

5
JohnB
select
  Field1, Field2...
from
  Table1
order by
  isnumeric(Field1) desc,
  case when isnumeric(Field1) = 1 then cast(Field1 as int) else null end,
  Field1

これにより、質問で指定した順序で値が返されます。

キャストがすべて実行されてもパフォーマンスはそれほど高くないため、別のアプローチは、データの整数コピーを格納するテーブルに別の列を追加し、最初にその列で、次に問題の列で並べ替えることです。これには、テーブルにデータを挿入または更新するロジックを変更して、両方の列にデータを取り込む必要があることは明らかです。それとも、データが挿入または更新されるたびに2番目の列にデータを挿入するためにテーブルにトリガーを配置します。

5
Luke Bennett

整数が短すぎる可能性があるため、varchar-columnをいつでもbigintに変換できます...

select cast([yourvarchar] as BIGINT)

しかし、常にアルファ文字に注意する必要があります

where ISNUMERIC([yourvarchar] +'e0') = 1

+ 'e0'は http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/isnumeric-isint-isnumber に由来します

これはあなたの声明につながります

SELECT
  *
FROM
  Table
ORDER BY
   ISNUMERIC([yourvarchar] +'e0') DESC
 , LEN([yourvarchar]) ASC

最初のソート列は数値を先頭に配置します。 2番目は長さでソートされるため、10が0001に先行します(これはバカですか?!)

これは、2番目のバージョンにつながります。

SELECT
      *
    FROM
      Table
    ORDER BY
       ISNUMERIC([yourvarchar] +'e0') DESC
     , RIGHT('00000000000000000000'+[yourvarchar], 20) ASC

2番目の列は右に「0」が埋め込まれるため、自然な並べ替えでは、先頭にゼロ(0、01、10、0100 ...)の整数が正しい順序で配置されます(正しい!)-ただし、すべてのアルファは「0」で拡張されます-chars(パフォーマンス)

3番目のバージョン:

 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

現在、数字は最初に「0」文字で埋められます(もちろん、長さ20を拡張できます)-数字を正しく並べ替えます-アルファのみがトリミングされます

4
Bernhard

「順序」の部分にこれを書くことは非常に簡単な方法で解決しました

ORDER BY (
sr.codice +0
)
ASC

これは非常にうまくいくようで、実際、次のソートがありました。

16079   Customer X 
016082  Customer Y
16413   Customer Z

0 の前に 16082は正しく考慮されます。

4
Orz

これはうまくいくようです:

select your_column  
from your_table  
order by   
case when isnumeric(your_column) = 1 then your_column else 999999999 end,  
your_column   
2
Corey Trager

このクエリは役に立ちます。このクエリでは、varcharが適切な順序で並べられたデータ型の列があります。たとえば、この列のデータは次のとおりです。-G1、G34、G10、G3。したがって、このクエリを実行すると、結果が表示されます:-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;
0
Nitika Chopra

これはあなたを助けるかもしれません、私は同じ問題を抱えたときにこれを試しました。

SELECT * FROM tab ORDER BY IIF(TRY_CAST(val AS INT) IS NULL, 1, 0),TRY_CAST(val AS INT);

0
Dennis
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

このリンク に従って、「$」が数字として順序付けられないようにするには、MONEY、INTにキャストする必要があります。

0
Matt Mitchell