数値としてのSQLオーダー文字列


137

VARCHARMySQLデータベースに関して保存されている番号があります。INT他の事情により製作出来ません。

並べ替えの際、数字ではなく文字として扱います。

データベースには

1 2 3 4 5 6 7 8 9 10...

私のページでは、次のような順序付きリストが表示されます:

1 10 2 3 4 5 6 7 8 9

昇順の番号で表示するにはどうすればよいですか?


5
確かに、データを文字列ではなく数値として保存する必要があります。
2012

@Oded非常に特殊な場合にのみ数値で並べ替えたい任意のデータ(設定など)を持つことができます。
Glutexo 2018

非常に興味深い記事- MSSQLのためですが、MySQLのために比較的類似しているはず:essentialsql.com/use-sql-server-to-sort-alphanumeric-values
AquaAlex

回答:


256

とにかく数値のみを格納する場合は、可能であれば、列のデータ型を数値に変更する必要があります。

それができない場合は、列の値をinteger 明示的にキャストして

select col from yourtable
order by cast(col as unsigned)

または暗黙的に、たとえば数値への変換を強制する数学演算を使用

select col from yourtable
order by col + 0

ところでMySQLは文字列を左から右に変換します。例:

string value  |  integer value after conversion
--------------+--------------------------------
'1'           |  1
'ABC'         |  0   /* the string does not contain a number, so the result is 0 */
'123miles'    |  123 
'$123'        |  0   /* the left side of the string does not start with a number */

3
col * 1による順序は完全に機能します。この背後にある魔法は何ですか?私はプロではありませんので、これはばかげた質問かもしれませんが、* 1はどのように数値に変更されますか?
Jamol 2012

12
MySQLは自動的に文字列を数値に変換して乗算を行います1
juergen d

1
最初のオプションは最も適切なオプションです。2番目のオプションには追加のステップがありますが、それ以下では機能しません。
Manatax 2014年

5
文字列と数値が混在していて、両方を並べ替えたい場合は、「order by col * 1、col」を使用します
Hayden Thring

1
@superphonic:結果はになりますdecimal
juergen d 2016

70

もう1つの方法は、シングルキャストを使用しないことです。

(キャストが許可されていないJPA 2.0を使用する人向け)

select col from yourtable
order by length(col),col

編集:正の整数に対してのみ機能します


9
これは良いもの
です。int

1
これはすべての場合で機能するわけではありません。頭の外で、うまくいかないケースは整数の混合です。負の数、先行ゼロのある数、分数のある数、単語と数の組み合わせ。
WonderWorker

3
キャストやジャグリングのない素晴らしいソリューション、+ 1
Maksim Luzik 2018年

一見してうまくいかなかったようですが、うまくいきました!ありがとうございました!
try2fly.b4ucry


17

並べ替えの対象となる列には、アルファベットと数値の任意の組み合わせがあるため、この投稿の提案を出発点として使用し、これを思い付きました。

DECLARE @tmp TABLE (ID VARCHAR(50));
INSERT INTO @tmp VALUES ('XYZ300');
INSERT INTO @tmp VALUES ('XYZ1002');
INSERT INTO @tmp VALUES ('106');
INSERT INTO @tmp VALUES ('206');
INSERT INTO @tmp VALUES ('1002');
INSERT INTO @tmp VALUES ('J206');
INSERT INTO @tmp VALUES ('J1002');

SELECT ID, (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END) IsNum
FROM @tmp
ORDER BY IsNum, LEN(ID), ID;

結果

ID
------------------------
106
206
1002
J206
J1002
XYZ300
XYZ1002

お役に立てれば


1 - ISNUMERIC(ID)代わりに(CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END)を使用して0を1に変更し、その逆も可能です。
S.Serpooshan 2018

7

これは私にとってはうまくいきます。

select * from tablename
order by cast(columnname as int) asc

理由を説明できますか?
スラビック

最も単純な答えは、必要なことを正確に実行し、文字列をintにキャストしてから、そのintを昇順で並べ替え、ファンキーなものを使用しないことです。)
denford mutseriwa

4

変換する別の方法。

文字列フィールドがある場合、次の方法でフィールドまたはその数値部分を変換できます。先行ゼロを追加して、すべての整数文字列を同じ長さにします。

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( stringfield ) ) , stringfield ) 

または、「tensymbols13」、「tensymbols1222」など、フィールドの一部で並べ替えます。

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( LEFT( stringfield , 10 ) ) ) , LEFT( stringfield , 10 ) ) 

2

文字のプレフィックスが付いている並べ替えフィールドも探していました。これが私が解決策を見つけたものです。これは、同じソリューションを探している人を助けるかもしれません。

フィールド値:

FL01,FL02,FL03,FL04,FL05,...FL100,...FL123456789

select SUBSTRING(field,3,9) as field from table order by SUBSTRING(field,3,10)*1 desc

SUBSTRING(field,3,9) 9は最大9桁の整数値を保持するのに十分な方法であるため、9を指定しました。

したがって、結果は123456789 123456788 123456787 ... 100 99 ... 2 1になります。


2

これは負の数、分数、文字列、すべてを処理します:

ORDER BY ISNUMERIC(col) DESC, Try_Parse(col AS decimal(10,2)), col;

2

同じソリューションを探している人を助けるかもしれません。

select * from tablename ORDER BY ABS(column_name)

0

AdonisJSを使用していて、ABC-202、ABC-201 ...などのIDが混在している場合は、生のクエリをクエリビルダーと組み合わせて、上記のソリューションを実装できます(https://stackoverflow.com/a/25061144/4040835)次のように:

const sortField =
  'membership_id'
const sortDirection =
  'asc'
const subquery = UserProfile.query()
  .select(
    'user_profiles.id',
    'user_profiles.user_id',
    'user_profiles.membership_id',
    'user_profiles.first_name',
    'user_profiles.middle_name',
    'user_profiles.last_name',
    'user_profiles.mobile_number',
    'countries.citizenship',
    'states.name as state_of_origin',
    'user_profiles.gender',
    'user_profiles.created_at',
    'user_profiles.updated_at'
  )
  .leftJoin(
    'users',
    'user_profiles.user_id',
    'users.id'
  )
  .leftJoin(
    'countries',
    'user_profiles.nationality',
    'countries.id'
  )
  .leftJoin(
    'states',
    'user_profiles.state_of_origin',
    'states.id'
  )
  .orderByRaw(
    `SUBSTRING(:sortField:,3,15)*1 ${sortDirection}`,
    {
      sortField: sortField,
    }
  )
  .paginate(
    page,
    per_page
  )

注: この行ではSUBSTRING(:sortField:,3,15)*1 ${sortDirection}

  1. 「3」は、数字の前の最後の非数値文字のインデックス番号を表します。混合IDが「ABC-123」の場合、インデックス番号は4になります。
  2. 「15」は、ハイフンの後に可能な限り多くの桁をキャッチするために使用されます。
  3. '1'は、部分文字列を数値に効果的にキャストする数学操作を実行します。

参照1:生のクエリのパラメーターバインディングの詳細については、https//knexjs.org/#Raw-Bindingsを 参照してください。参照2:Adonisの生のクエリ:https : //adonisjs.com/docs/4.1/query-builder# _raw_queries


-3

フィールドをVARCHARではなくINTに変更します。

他の事情によりINT化できません。

次に、依存する状況を最初に修正します。そうでなければ、あなたは本当の根本的な問題を回避しています。MySQL CASTの使用はオプションですが、修正する必要のある不良スキーマをマスクします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.