Chuỗi thứ tự SQL là số


137

Tôi có số được lưu VARCHARvào cơ sở dữ liệu MySQL. Tôi không thể làm cho họ INTdo một số trường hợp tùy thuộc khác.

Đó là lấy họ làm nhân vật không phải là số trong khi sắp xếp.

Trong cơ sở dữ liệu tôi có

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

Trên trang của tôi, nó hiển thị danh sách theo thứ tự như thế này:

1 10 2 3 4 5 6 7 8 9

Làm thế nào tôi có thể làm cho nó xuất hiện theo thứ tự tăng dần?


5
Chắc chắn bạn nên lưu trữ dữ liệu dưới dạng số, thay vì chuỗi.
Oded

@Oded Bạn có thể có một số dữ liệu tùy ý (ví dụ: cài đặt) mà bạn muốn đặt hàng theo giá trị số của nó chỉ trong các trường hợp rất đặc biệt.
Glutexo

bài viết rất thú vị - là dành cho MSSQL nhưng phải tương đối giống nhau cho MySQL: essentialsql.com/use-sql-server-to-sort-alphanumeric-values
AquaAlex

Câu trả lời:


256

Nếu có thể, bạn nên thay đổi kiểu dữ liệu của cột thành một số nếu bạn chỉ lưu trữ số.

Nếu bạn không thể làm điều đó thì hãy chuyển giá trị cột của bạn thành integer rõ ràng với

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

hoặc ngầm định với một hoạt động toán học buộc phải chuyển đổi thành số

select col from yourtable
order by col + 0

BTW MySQL chuyển đổi các chuỗi từ trái sang phải. Ví dụ:

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
đặt hàng bởi col * 1 hoạt động hoàn hảo. Điều kỳ diệu đằng sau điều này là gì? Xin lỗi tôi không chuyên nghiệp nên đây có thể là câu hỏi ngớ ngẩn nhưng Làm thế nào * 1 làm cho nó thay đổi thành số?
Jamol

12
MySQL tự động chuyển đổi chuỗi thành một số để thực hiện phép nhân với1
juergen d

1
Tùy chọn đầu tiên là thích hợp nhất, tùy chọn thứ hai có thêm một bước, nhưng nó hoạt động không phải là ít.
Manatax

5
và nếu bạn có chuỗi và số hỗn hợp và muốn cả hai được sắp xếp, hãy sử dụng "order by col * 1, col"
Hayden Thring

1
@superphonic: Kết quả sẽ là decimal.
juergen d

70

Một cách khác, mà không sử dụng một diễn viên duy nhất.

(Đối với những người sử dụng JPA 2.0, nơi không cho phép truyền hình)

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

EDIT: chỉ hoạt động cho các số nguyên dương


9
đây là một cái tốt, cái đó hoạt động với cột cũng chứa cả int và chuỗi
Sbean A.Suk

1
Điều này sẽ không hoạt động trong mọi trường hợp. Ngoài đỉnh đầu, các trường hợp không hoạt động là hỗn hợp của toàn bộ số với; số âm, số có số 0 đứng đầu, số có phân số và từ và số kết hợp.
WonderWorker

3
giải pháp tuyệt vời mà không có bất kỳ kiểu đúc và tung hứng nào xung quanh, +1
Maksim Luzik

dường như không làm việc từ cái nhìn đầu tiên, nhưng nó đã làm việc! Cảm ơn bạn!
thử2fly.b4ucry


17

Cột tôi sắp xếp có bất kỳ sự kết hợp nào giữa alpha và số, vì vậy tôi đã sử dụng các đề xuất trong bài đăng này làm điểm bắt đầu và đưa ra điều này.

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;

Các kết quả

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

Hi vọng điêu nay co ich


Bạn có thể chỉ cần sử dụng 1 - ISNUMERIC(ID)thay vì thay (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END)đổi 0 thành 1 và ngược lại.
S.Serpooshan

7

Điều này làm việc cho tôi.

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

bạn có thể giải thích lý do tại sao?
Slasta

câu trả lời đơn giản nhất, thực hiện chính xác những gì cần thiết, chuyển chuỗi thành int, sau đó sắp xếp theo int theo thứ tự tăng dần, không có nội dung thú vị nào :)
denford mutseriwa

4

Một cách khác để chuyển đổi.

Nếu bạn có trường chuỗi, bạn có thể chuyển đổi nó hoặc phần số của nó theo cách sau: thêm các số 0 đứng đầu để làm cho tất cả các chuỗi số nguyên có độ dài bằng nhau.

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

hoặc đặt hàng theo một phần của một lĩnh vực nào đó như 'tenymbols13', 'tenymbols1222', v.v.

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

2

Tôi cũng đang tìm một trường sắp xếp có tiền tố chữ cái. Đây là những gì tôi tìm ra giải pháp. Điều này có thể giúp những người đang tìm kiếm giải pháp tương tự.

Giá trị trường:

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) tôi đặt 9 vì 9 là cách đủ để tôi giữ các giá trị nguyên tối đa 9 chữ số.

Vậy kết quả sẽ là 123456789 123456788 123456787 ... 100 99 ... 2 1


2

Điều này sẽ xử lý số âm, phân số, chuỗi, mọi thứ:

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

2

Nó có thể giúp những người đang tìm kiếm giải pháp tương tự.

select * from tablename ORDER BY ABS(column_name)

0

Nếu bạn đang sử dụng AdonisJS và có các ID hỗn hợp như ABC-202, ABC-201 ..., bạn có thể kết hợp các truy vấn thô với Trình tạo truy vấn và triển khai giải pháp ở trên ( https://stackoverflow.com/a/25061144/4040835 ) như sau:

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
  )

GHI CHÚ: Trong dòng này : SUBSTRING(:sortField:,3,15)*1 ${sortDirection},

  1. '3' là viết tắt của số chỉ mục của ký tự không số cuối cùng trước các chữ số. Nếu ID hỗn hợp của bạn là "ABC-123", số chỉ mục của bạn sẽ là 4.
  2. '15' được sử dụng để bắt càng nhiều số chữ số càng tốt sau dấu gạch nối.
  3. '1' thực hiện một phép toán trên chuỗi con, điều này có hiệu quả chuyển chuỗi con thành một số.

Tham chiếu 1: Bạn có thể đọc thêm về các ràng buộc tham số trong các truy vấn thô tại đây: https://knexjs.org/#Raw-Bindings Tham chiếu 2: Truy vấn thô Adonis: https://adonisjs.com/docs/4.1/query-builder# _raw_queries


-3

Thay đổi lĩnh vực của bạn thành INT thay vì VARCHAR.

Tôi không thể làm cho họ INT do một số trường hợp tùy thuộc khác.

Sau đó sửa các trường hợp tùy thuộc trước. Nếu không, bạn đang làm việc xung quanh vấn đề thực sự tiềm ẩn. Sử dụng MySQL CAST là một tùy chọn, nhưng nó che giấu lược đồ xấu của bạn cần được sửa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.