Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

ใช้ Comparison Operator กับ Numeric String ใน MySQL ด้วย SUBSTRING

ปัญหา: เปรียบเทียบ String ที่มีตัวเลข

String Comparison ทำงานแบบ Lexicographical (ตัวอักษร):

'10' > '2'   -- FALSE เพราะ '1' < '2'
'5-9' > '4-8' -- TRUE แต่ไม่ได้หมายความว่า 5 > 4 ในทุกกรณี

การเตรียมข้อมูล

mysql> CREATE TABLE DemoTable1881 (
    UserId INT,
    UserEducationGap VARCHAR(20)
);

mysql> INSERT INTO DemoTable1881 VALUES
    (101, '5-9'), (102, '2-4'), (103, '4-8'), (104, '7-12');

เปรียบเทียบส่วนตัวเลขแรก (ก่อน Hyphen)

mysql> SELECT * FROM DemoTable1881
    WHERE CAST(SUBSTRING(UserEducationGap, 1, INSTR(UserEducationGap, '-') - 1) AS SIGNED) >= 4;

ผลลัพธ์ (5-9, 4-8, 7-12 มีตัวเลขแรก >= 4):

+--------+------------------+
| UserId | UserEducationGap |
+--------+------------------+
|    101 | 5-9              |
|    103 | 4-8              |
|    104 | 7-12             |
+--------+------------------+

การแยกส่วนตัวเลข

-- SUBSTRING(str, start, length)
-- INSTR(str, substr) หาตำแหน่ง substr ใน str

-- '5-9': INSTR('-') = 2, SUBSTRING(1, 1) = '5'
-- '7-12': INSTR('-') = 2, SUBSTRING(1, 1) = '7'
-- '10-20': INSTR('-') = 3, SUBSTRING(1, 2) = '10'

ปรับปรุงรองรับหลายหลัก

SELECT * FROM DemoTable1881
WHERE CAST(SUBSTRING_INDEX(UserEducationGap, '-', 1) AS SIGNED) >= 4;
-- SUBSTRING_INDEX ใช้งานง่ายกว่า: ส่วนก่อน - ตัวแรก

CAST vs CONVERT

CAST(expr AS type)
CONVERT(expr, type)

-- SIGNED = Signed Integer
-- UNSIGNED = Unsigned Integer
-- DECIMAL(m,d) = ทศนิยม
-- CHAR(N) = String

แนวทางแก้ไขข้อมูล (Best Practice)

-- แยกเก็บ Min/Max แทน String Range
CREATE TABLE education_gaps (
    user_id INT,
    gap_min INT,
    gap_max INT
);

-- Query ง่ายและใช้ Index ได้
SELECT * FROM education_gaps WHERE gap_min >= 4;

ข้อสรุป

  • หลีกเลี่ยงเก็บ Numeric Range ใน String
  • ถ้าบังคับต้อง Query ให้ Parse ออกมาก่อน (SUBSTRING_INDEX + CAST)
  • Performance: Full Scan, ไม่ใช้ Index