สตริงคำสั่ง SQL เป็นตัวเลข


144

ฉันบันทึกตัวเลขไว้ในVARCHARฐานข้อมูล MySQL ฉันไม่สามารถสร้างได้INTเนื่องจากสถานการณ์อื่น ๆ

มันกำลังทำให้พวกเขาเป็นอักขระไม่ใช่ตัวเลขในขณะที่เรียงลำดับ

ในฐานข้อมูลฉันมี

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

ในหน้าของฉันจะแสดงรายการสั่งซื้อดังนี้:

1 10 2 3 4 5 6 7 8 9

ฉันจะทำให้มันปรากฏเรียงตามตัวเลขจากน้อยไปมากได้อย่างไร


5
แน่นอนคุณควรจัดเก็บข้อมูลเป็นตัวเลขแทนที่จะเป็นสตริง
Oded

@Oded คุณสามารถมีข้อมูลตามอำเภอใจ (เช่นการตั้งค่า) ซึ่งคุณต้องการเรียงลำดับตามค่าตัวเลขในกรณีพิเศษเท่านั้น
Glutexo

บทความที่น่าสนใจมาก - ใช้สำหรับ MSSQL แต่ควรจะค่อนข้างคล้ายกับ MySQL: essentialsql.com/use-sql-server-to-sort-alphanumeric-values
AquaAlex

คำตอบ:


268

หากเป็นไปได้คุณควรเปลี่ยนประเภทข้อมูลของคอลัมน์เป็นตัวเลขหากคุณเก็บเฉพาะตัวเลขเท่านั้น

หากคุณไม่สามารถทำได้ให้โยนค่าคอลัมน์ของคุณให้integer ชัดเจนด้วย

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

หรือโดยปริยายเช่นการดำเนินการทางคณิตศาสตร์ซึ่งบังคับให้แปลงเป็นตัวเลข

select col from yourtable
order by col + 0

BTW 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 */

5
สั่งโดย col * 1 ทำงานได้อย่างสมบูรณ์แบบ ความมหัศจรรย์ที่อยู่เบื้องหลังสิ่งนี้คืออะไร? ขออภัยฉันไม่ใช่มืออาชีพดังนั้นนี่อาจเป็นคำถามโง่ ๆ แต่ * 1 เปลี่ยนเป็นตัวเลขได้อย่างไร
Jamol

13
MySQL จะแปลงสตริงเป็นตัวเลขโดยอัตโนมัติเพื่อทำการคูณด้วย1
juergen d

1
ตัวเลือกแรกเหมาะสมที่สุดตัวเลือกที่สองมีขั้นตอนพิเศษ แต่ใช้งานได้ไม่น้อย
Manatax

7
และถ้าคุณมีสตริงและตัวเลขผสมกันและต้องการให้เรียงลำดับทั้งคู่ให้ใช้ "order by col * 1, col"
Hayden Thring

1
@superphonic: ผลลัพธ์จะเป็นdecimalอย่างไร
juergen d

73

อีกวิธีหนึ่งโดยไม่ต้องใช้การร่ายเดี่ยว

(สำหรับผู้ที่ใช้ JPA 2.0 ซึ่งไม่อนุญาตให้ทำการแคสติ้ง)

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

แก้ไข: ใช้ได้กับจำนวนเต็มบวกเท่านั้น


9
นี่เป็นสิ่งที่ดีที่ทำงานร่วมกับคอลัมน์ที่มีทั้ง int และ string ด้วย
Sruit A. Suk

1
วิธีนี้จะใช้ไม่ได้ในทุกกรณี กรณีที่ไม่สามารถใช้งานได้คือการผสมของจำนวนเต็มด้วย; จำนวนลบตัวเลขที่มีเลขศูนย์นำหน้าตัวเลขที่มีเศษส่วนและคำและตัวเลขรวมกัน
WonderWorker

3
ทางออกที่ดีโดยไม่ต้องมีการคัดเลือกนักแสดงและการเล่นกลรอบ ๆ +1
Maksim Luzik

ดูเหมือนจะไม่ได้ผลตั้งแต่แรกเห็น แต่มันได้ผล! ขอบคุณ!
try2fly.b4ucry


18

คอลัมน์ที่ฉันกำลังเรียงลำดับมีทั้งตัวอักษรและตัวเลขผสมกันดังนั้นฉันจึงใช้คำแนะนำในโพสต์นี้เป็นจุดเริ่มต้นและคิดขึ้นมา

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
คุณสามารถใช้1 - ISNUMERIC(ID)แทน(CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END)การเปลี่ยน 0 เป็น 1 และในทางกลับกันได้
สารภูซาน

7

สิ่งนี้ใช้ได้กับฉัน

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

คุณอธิบายได้ไหมว่าทำไม
Slavik

คำตอบที่ง่ายที่สุดนั่นคือสิ่งที่ต้องการอย่างแท้จริงโยนสตริงเป็น 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



0

หากคุณใช้ AdonisJS และมี ID ผสมกันเช่น ABC-202, ABC-201 ... คุณสามารถรวมการสืบค้นข้อมูลดิบกับ Query Builder และใช้โซลูชันด้านบนได้ ( 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'หมายถึงหมายเลขดัชนีของอักขระที่ไม่ใช่ตัวเลขตัวสุดท้ายก่อนตัวเลข หากรหัสผสมของคุณคือ "ABC-123" หมายเลขดัชนีของคุณจะเป็น 4
  2. '15'ใช้เพื่อจับเป็นจำนวนหลักหลังยัติภังค์
  3. '1'ดำเนินการทางคณิตศาสตร์บนสตริงย่อยซึ่งส่งผลให้สตริงย่อยเป็นตัวเลขได้อย่างมีประสิทธิภาพ

Ref 1: คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการเชื่อมโยงพารามิเตอร์ในแบบสอบถามดิบได้ที่นี่: https://knexjs.org/#Raw-Bindings Ref 2: Adonis Raw Queries: https://adonisjs.com/docs/4.1/query-builder# _raw_queries


-4

เปลี่ยนฟิลด์ของคุณให้เป็น INT แทน VARCHAR

ฉันไม่สามารถทำให้ INT ได้เนื่องจากสถานการณ์อื่น ๆ

จากนั้นแก้ไขสถานการณ์ที่เกิดขึ้นก่อน มิฉะนั้นคุณกำลังแก้ไขปัญหาพื้นฐานที่แท้จริง การใช้ MySQL CAST เป็นทางเลือกหนึ่ง แต่เป็นการปิดบังสคีมาที่ไม่ดีซึ่งควรได้รับการแก้ไข

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.