web-dev-qa-db-ja.com

SQLで数値を含む文字列列を並べ替えますか?

文字列列(を含む数値)をソートしようとしています。

// SELECT `name` FROM `mytable` ORDER BY `name` ASC
+----------+
+-- name --+
+----------+
+-- a 1 ---+
+-- a 12 --+
+-- a 2 ---+
+-- a 3 ---+

Mysqlの自然なソートアルゴリズムがa 12a 1これはほとんどのアプリで問題ありません)、しかし私には固有のニーズがあるため、結果をこのようにソートする必要があります。

+----------+
+-- name --+
+----------+
+-- a 1 ---+
+-- a 2 ---+
+-- a 3 ---+
+-- a 12 --+

SQLのみで可能ですか、それともアプリケーションレベルで結果セットを操作する必要がありますか?

25
Ish

仮定に行くと、これは常にWord_space_NUMBERですこれはうまくいくはずです:

SELECT   *
FROM     table
ORDER BY CAST(SUBSTRING(column,LOCATE(' ',column)+1) AS SIGNED)

[〜#〜] position [〜#〜] を使用してスペースを検索し、 [〜#〜] substring [〜#〜] を使用してその後の数値を取得し、 [〜#〜] cast [〜#〜] 比較可能な値にします。

列に別のパターンがある場合は、お知らせください。より良い回避策を考案します。


[〜#〜] edit [〜#〜]動作することが証明されています:

mysql> INSERT INTO t (st) VALUES ('a 1'),('a 12'),('a 6'),('a 11');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM t ORDER BY st;
+----+------+
| id | st   |
+----+------+
|  1 | a 1  |
|  4 | a 11 |
|  2 | a 12 |
|  3 | a 6  |
+----+------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM t ORDER BY CAST(SUBSTRING(st,LOCATE(' ',st)+1) AS SIGNED);
+----+------+
| id | st   |
+----+------+
|  1 | a 1  |
|  3 | a 6  |
|  4 | a 11 |
|  2 | a 12 |
+----+------+

mysql> INSERT INTO t (st) VALUES ('b 1'),('b 12'),('b 6'),('b 11');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM t ORDER BY CAST(SUBSTRING(st,LOCATE(' ',st)+1) AS SIGNED);
+----+------+
| id | st   |
+----+------+
|  1 | a 1  |
|  5 | b 1  |
|  3 | a 6  |
|  7 | b 6  |
|  4 | a 11 |
|  8 | b 11 |
|  2 | a 12 |
|  6 | b 12 |
+----+------+
8 rows in set (0.00 sec)

mysql> SELECT * FROM t ORDER BY LEFT(st,LOCATE(' ',st)), CAST(SUBSTRING(st,LOCATE(' ',st)+1) AS SIGNED);
+----+------+
| id | st   |
+----+------+
|  1 | a 1  |
|  3 | a 6  |
|  4 | a 11 |
|  2 | a 12 |
|  5 | b 1  |
|  7 | b 6  |
|  8 | b 11 |
|  6 | b 12 |
+----+------+
8 rows in set (0.00 sec)

私の不完全なテーブル/列名を無視しますが、正しい結果が得られます。また、少し進んで、文字の接頭辞を数値で区切るために二重ソートを追加しました。

編集SUBSTRING_INDEXは少し読みやすくします。

ORDER BY SUBSTRING_INDEX(st, " ", 1) ASC, CAST(SUBSTRING_INDEX(st, " ", -1) AS SIGNED)
36
Brad Christie

あなたはこれを試すことができます:

ORDER BY CASE
  WHEN ISNUMERIC(column) THEN cast(column as int) 
  else ascii(column[1,1]) 
end
2
tzviki

MySQL CAST/Convert 関数を見てください。

SELECT name FROM mytable ORDER BY CAST(name AS INTEGER) ASC;

編集:私は読んだ:

文字列列(数値を含む)をソートしようとしています。

...しかし、結果セットを見てみました。 aも実際にはコンテンツの一部ですか?その場合、 [〜#〜] mid [〜#〜] のような関数を使用して、数値のみを抽出し、それをキャストできます。

しかし、allの行にaのみが含まれ、変化がない場合は、省略してもよいでしょう...

1
Jim Brissom

別のオプションとして、数値の左側にスペースを文字列に埋め込んで(Wordと数値の間にスペースを追加する)、結果の文字列を使用してソートすることもできます。次のようになります。

ORDER BY INSERT(
  column,
  LOCATE(' ', column),
  0,
  SPACES(20 - LENGTH(column) + LOCATE(' ', column))
)

文字列は「Wordの後にスペースが続き、その後に数値が続く」というパターンであると見なされ、数値は負でないと見なされます(そうしないと、正しくソートされません)。ハードコードされた20は任意に選択され、文字列の数値部分の可能な最大長であると想定されています。

0
Andriy M

ここで、Convertを使用して次のクエリで別のソリューションを見つけました

select * from tablename where columnname like '%a%' order by Convert(smallint,Replace(columnname,'a',''))
0
Hussain