MySQL ชอบ () ใช่ไหม


273

ข้อความค้นหาปัจจุบันของฉันดูเหมือนว่า:

SELECT * FROM fiberbox f WHERE f.fiberBox LIKE '%1740 %' OR f.fiberBox LIKE '%1938 %' OR f.fiberBox LIKE '%1940 %'

ฉันได้มองไปรอบ ๆ และไม่พบสิ่งใดที่คล้ายกับ LIKE IN () - ฉันจินตนาการว่ามันทำงานได้เช่นนี้:

SELECT * FROM fiberbox f WHERE f.fiberbox LIKE IN('%140 %', '%1938 %', '%1940 %')

ความคิดใด ๆ ฉันแค่คิดถึงปัญหาในทางที่ผิด - บางคำสั่งคลุมเครือฉันไม่เคยเห็น

MySQL 5.0.77-community-log


1
WHERE FIND_IN_SET(f.fiberbox, "1740,1938,1940")
Gjermund Dahl

2
FIND_IN_SET ไม่รับไวลด์การ์ดเช่น%
Sebastián Grignoli

คำตอบ:


454

REGEXP อาจจะมีประสิทธิภาพมากขึ้น แต่คุณจะต้องมาตรฐานมันเพื่อให้แน่ใจว่าเช่น

SELECT * from fiberbox where field REGEXP '1740|1938|1940'; 

2
ฉันชอบคำตอบนี้ - รวดเร็วง่ายมี "ตัวเลือก" ทั้งหมดในหนึ่งบรรทัดเหมือนที่ฉันต้องการ (แก้ไขง่าย) ในชุดผลลัพธ์ขนาดเล็กที่ฉันกำหนดเป้าหมายจะไม่มีประสิทธิภาพลดลงเลย
ไมเคิลเวลส์

51
มากกว่า 1 ล้านแถวในตารางของฉัน REGEX arround 0.0009 และ LIKE arround 0.0005 ถ้ามากกว่า 5 REGEX ให้กำหนด 0.0012 ...
David Bélanger

10
ฉันมีปัญหาที่REGEXPช้าอย่างไม่ได้ตั้งใจ แต่ฉันต้องการความยืดหยุ่นของ REGEXP เพื่อ จำกัด ผลลัพธ์ของฉันให้แคบลงเกินกว่าที่LIKEควรจะให้ ฉันมาด้วยวิธีไฮบริดที่ผมใช้ทั้งสองLIKEและREGEXP; แม้จะมีREGEXPส่วนที่เพียงพอที่จะให้ผลลัพธ์ที่ถูกต้องแก่ฉัน แต่ก็LIKEอนุญาตให้ MySQL ลดผลลัพธ์ที่ได้ก่อนที่จะใช้REGEXPเกณฑ์ที่ช้ากว่า
mpen

1
ในการรับค่า regexp จากคอลัมน์:(select group_concat(myColumn separator '|') from..)
daVe

5
การเพิ่มข้อมูลประสิทธิภาพ บน MySql 5.5 ในตารางที่มีแถว 229M คำที่เหลือ 1 คำจะถูกค้นหา 3 char: REGEXP: 16s, LIKE: 8.5s; 2 คำศัพท์: REGEXP: 22.1 วินาที, ชอบ: 9.69; '^ (ฮีโมโกลบิน | hematr? ocrit). *' เทียบกับคำ 3 คำเช่น: REGEXP: 36.3, เช่น: 9.59
Jesse Clark

181

คำตอบของ Paul Dixon นั้นยอดเยี่ยมสำหรับฉัน เพื่อเพิ่มนี้นี่คือสิ่งที่ฉันสังเกตเห็นสำหรับผู้ที่สนใจในการใช้ REGEXP:

หากต้องการบรรลุตัวกรอง LIKE หลายรายการด้วย Wildcards:

 SELECT * FROM fiberbox WHERE field LIKE '%1740 %'
                           OR field LIKE '%1938 %'
                           OR field LIKE '%1940 %';  

ใช้ทางเลือก REGEXP:

 SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 |1940 ';

ค่าภายในอัญประกาศ REGEXP และระหว่าง | (OR) ตัวดำเนินการจะถือว่าเป็นอักขระตัวแทน โดยทั่วไป REGEXP จะต้องการนิพจน์ตัวแทนเช่น (. *) 1740 (. *) เพื่อให้ทำงานเป็น% 1740%

หากคุณต้องการควบคุมตำแหน่งของ wildcard ให้ใช้ตัวแปรเหล่านี้บางส่วน:

หากต้องการบรรลุ LIKE ด้วยตำแหน่งไวด์การ์ดที่ควบคุม:

SELECT * FROM fiberbox WHERE field LIKE '1740 %'
                          OR field LIKE '%1938 '
                          OR field LIKE '%1940 % test';  

ใช้:

SELECT * FROM fiberbox WHERE field REGEXP '^1740 |1938 $|1940 (.*) test';
  • การวาง ^ ด้านหน้าของค่าระบุว่าเป็นจุดเริ่มต้นของบรรทัด

  • วาง $ หลังจากค่าระบุจุดสิ้นสุดของบรรทัด

  • การวาง (. *) ทำตัวเหมือนสัญลักษณ์ตัวแทน%

  • ส่วน บ่งชี้อักขระเดี่ยวใด ๆ ยกเว้นตัวแบ่งบรรทัด การวาง ข้างใน () ด้วย * (. *) เพิ่มรูปแบบการทำซ้ำเพื่อระบุจำนวนอักขระจนถึงจุดสิ้นสุดบรรทัด

มีวิธีที่มีประสิทธิภาพมากขึ้นในการ จำกัด การจับคู่ที่เฉพาะเจาะจง แต่ต้องมีการตรวจสอบนิพจน์ปกติเพิ่มเติม หมายเหตุ: รูปแบบ regex บางรูปแบบอาจไม่ทำงานในคำสั่ง MySQL คุณจะต้องทดสอบรูปแบบของคุณและดูว่าอะไรทำงาน

สุดท้ายเพื่อบรรลุตัวกรอง LIKE หลายอันและไม่ชอบ LIKE:

SELECT * FROM fiberbox WHERE field LIKE '%1740 %'
                          OR field LIKE '%1938 %'
                          OR field NOT LIKE '%1940 %'
                          OR field NOT LIKE 'test %'
                          OR field = '9999';

ใช้ทางเลือก REGEXP:

SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 |^9999$'
                          OR field NOT REGEXP '1940 |^test ';

หรือทางเลือกผสม:

SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 '
                          OR field NOT REGEXP '1940 |^test '
                          OR field NOT LIKE 'test %'
                          OR field = '9999';

แจ้งให้ทราบฉันแยกไม่ได้ตั้งค่าในตัวกรองแยกที่ ฉันทดลองกับการใช้รูปแบบการปฏิเสธรูปแบบการมองไปข้างหน้าและอื่น ๆ อย่างไรก็ตามนิพจน์เหล่านี้ไม่ได้ให้ผลลัพธ์ตามที่ต้องการ ในตัวอย่างแรกข้างต้นฉันใช้ ^ 9999 $ เพื่อระบุการจับคู่ที่ตรงกัน สิ่งนี้ช่วยให้คุณสามารถเพิ่มการจับคู่ที่เฉพาะเจาะจงด้วยการจับคู่ตัวแทนในการแสดงออกเดียวกัน อย่างไรก็ตามคุณยังสามารถผสมคำสั่งประเภทนี้ตามที่คุณเห็นในตัวอย่างที่สองที่แสดง

เกี่ยวกับประสิทธิภาพฉันทำการทดสอบเล็กน้อยกับตารางที่มีอยู่และไม่พบความแตกต่างระหว่างรูปแบบของฉัน อย่างไรก็ตามฉันคิดว่าประสิทธิภาพอาจมีปัญหากับฐานข้อมูลที่ใหญ่กว่าฟิลด์ที่ใหญ่กว่าจำนวนการบันทึกที่มากขึ้นและตัวกรองที่ซับซ้อนยิ่งขึ้น

เช่นเคยใช้ตรรกะข้างต้นตามที่เหมาะสม

หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับนิพจน์ทั่วไปฉันขอแนะนำ www.regular-expressions.info เป็นเว็บไซต์อ้างอิงที่ดี


โปรดทราบว่าเขตข้อมูลที่มีค่า NULL จะไม่ตรงกับ REGEXP คุณสามารถใช้ IFNULL เพื่อแก้ปัญหานี้ WHERE IFNULL(field, '') NOT REGEXP '1740 | 1938'

@DanyMarcoux จะทำอย่างไรถ้าฉันต้องการใช้ (. *) แต่มันควรจะทำหน้าที่เหมือน FIELDNAME LIKE '%%' วิธีการใช้งานกับ regexp ดังนั้นเมื่อสตริงว่างถูกส่งผ่าน มันควรดึงข้อมูลทั้งหมด ..
shzyincu

ฟิลด์ตำแหน่งที่ไม่ต้องการ '% 1940%' หรือฟิลด์ที่ไม่ชอบ 'ทดสอบ%' จะส่งคืนแถวทั้งหมดเสมอ นั่นอาจมีส่วนทำให้ไม่ได้ผลลัพธ์ตามที่คุณต้องการ?
Herbert Van-Vliet

14

คุณสามารถสร้างมุมมองแบบอินไลน์หรือตารางชั่วคราวกรอกค่าและออก:

SELECT  *
FROM    fiberbox f
JOIN    (
        SELECT '%1740%' AS cond
        UNION ALL
        SELECT '%1938%' AS cond
        UNION ALL
        SELECT '%1940%' AS cond
        ) с
ON      f.fiberBox LIKE cond

อย่างไรก็ตามสิ่งนี้สามารถส่งคืนคุณหลายแถวสำหรับfiberboxสิ่งที่คล้าย'1740, 1938'กันดังนั้นแบบสอบถามนี้สามารถทำให้คุณดีขึ้น:

SELECT  *
FROM    fiberbox f
WHERE   EXISTS
        (
        SELECT  1
        FROM    (
                SELECT '%1740%' AS cond
                UNION ALL
                SELECT '%1938%' AS cond
                UNION ALL
                SELECT '%1940%' AS cond
                ) с
        WHERE   f.fiberbox LIKE cond
        )


7

ขออภัยไม่มีการดำเนินการคล้ายกับLIKE INใน mysql

หากคุณต้องการใช้ตัวดำเนินการ LIKE โดยไม่ต้องเข้าร่วมคุณจะต้องทำดังนี้:

(field LIKE value OR field LIKE value OR field LIKE value)

คุณรู้ไหมว่า MySQL จะไม่ปรับให้เหมาะกับข้อความค้นหานั้น FYI


4

เพียงทราบกับทุกคนที่ลองใช้ REGEXP เพื่อใช้งานฟังก์ชั่น "LIKE IN"

ในช่วยให้คุณทำ:

field IN (
'val1',
'val2',
'val3'
)

ใน REGEXP สิ่งนี้จะไม่ทำงาน

REGEXP '
val1$|
val2$|
val3$
'

ต้องอยู่ในบรรทัดเดียวเช่นนี้:

REGEXP 'val1$|val2$|val3$'

3

พลิกตัวถูกดำเนินการ

'a,b,c' like '%'||field||'%'

2
เมื่อคุณมีข้อมูลบางอย่างชัดเจนจะเท่ากับบางสิ่งบางอย่างเช่น Enum สำหรับ Grads 'a', 'b', 'c' แต่ไม่ใช่ab, ac หรือ bc create table x(en enum('a,b,c')));insert into x values('a'),('b') en เป็นเพียงa หรือ b ที่ทำวิธีนี้โดยการพลิก oprands select * from, x where 'a,c' like concat('%',en,'%')สามารถปลอดภัยในSQL Injunction ไม่จำเป็นต้องหลบเลี่ยงตัวอักษรเช่น$ ^ เป็นต้น

สิ่งนี้ไม่เทียบเท่าและจะไม่ทำงานสำหรับกรณีทั่วไป ถ้าคุณรู้ว่าfieldจะไม่สามารถอยู่ตรงa, bหรือแล้วคุณควรใช้c field IN ('a', 'b', 'c')แต่โดยทั่วไปแล้วสิ่งนี้ไม่สามารถแทนที่ได้field LIKE '%a%' OR field LIKE '%b%' OR ...เพราะฟิลด์ตัวเองอาจเป็นสิ่งmagicที่จะทำให้'magic' LIKE '%a%'เป็นจริง แต่การแสดงออกที่'a,b,c' LIKE '%magic%'ผิดพลาด
ADTC


2

เพียงปลายเล็กน้อย:

ฉันชอบที่จะใช้ตัวแปรRLIKE (คำสั่งเดียวกับREGEXP ) เพราะมันฟังดูคล้ายกับภาษาธรรมชาติและสั้นกว่า ดีเพียง 1 ตัวอักษร

คำนำหน้า "R" ใช้สำหรับ Reg ประสบการณ์แน่นอน


0

คุณจะได้รับผลลัพธ์ที่ต้องการด้วยความช่วยเหลือของนิพจน์ปกติ

SELECT fiberbox from fiberbox where fiberbox REGEXP '[1740|1938|1940]';

เราสามารถทดสอบแบบสอบถามด้านบนกรุณาคลิกซอฟต์ดริล SQL

SELECT fiberbox from fiberbox where fiberbox REGEXP '[174019381940]';

เราสามารถทดสอบแบบสอบถามด้านบนกรุณาคลิกซอฟต์ดริล SQL


1
นี่เป็นนิพจน์ทั่วไปที่ไม่ถูกต้อง [...]เป็นชุดอักขระหมายถึงอักขระใด ๆ ในชุดนั้นเพียงพอที่จะถูกมองว่าเป็นการแข่งขัน ดังนั้นค่าใด ๆกับตัวเลข ' 0, 1, 3, 4, 7, 8, 9หรือ|ตัวอักษรท่อจะตรงนี้
Martijn Pieters
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.