มีการรวมกันของ "LIKE" และ "IN" ใน SQL หรือไม่


341

ใน SQL I (เศร้า) มักจะต้องใช้LIKEเงื่อนไข "" เนื่องจากฐานข้อมูลที่ละเมิดกฎการปรับมาตรฐานเกือบทุกครั้ง ฉันไม่สามารถเปลี่ยนแปลงได้ในตอนนี้ แต่นั่นไม่เกี่ยวข้องกับคำถาม

นอกจากนี้ฉันมักจะใช้เงื่อนไขเช่นWHERE something in (1,1,2,3,5,8,13,21)เพื่อการอ่านที่ดีขึ้นและความยืดหยุ่นของคำสั่ง SQL ของฉัน

มีวิธีใดบ้างที่สามารถรวมสองสิ่งนี้โดยไม่ต้องเขียนตัวเลือกย่อยที่ซับซ้อน?

ฉันต้องการบางสิ่งที่ง่ายเหมือนWHERE something LIKE ('bla%', '%foo%', 'batz%')แทนที่จะทำสิ่งนี้:

WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'

ฉันทำงานกับ SQl Server และ Oracle ที่นี่ แต่ฉันสนใจถ้าเป็นไปได้ใน RDBMS ใด ๆ เลย


1
คุณต้องทำและชอบหรือ: และ (บางสิ่งเช่น '% thing%' หรือสิ่งที่ต้องการ '% thing%' หรือสิ่งที่ต้องการ '% thing%')
Cosmic Hawk

ฉันหวังว่าเรามีของ Teradata like any/ like all: stackoverflow.com/questions/40475982/sql-like-any-vs-like-all (สำหรับบันทึกนี้ได้รับการร้องขอในฟอรัม Oracle Community Ideas community.oracle.com/ideas/11592 )
William Robertson

คำตอบ:


196

ไม่มีการรวมกันของ LIKE & IN ใน SQL, น้อยกว่ามากใน TSQL (SQL Server) หรือ PLSQL (Oracle) สาเหตุส่วนหนึ่งเป็นเพราะการค้นหาข้อความแบบเต็ม (FTS) เป็นทางเลือกที่แนะนำ

การปรับใช้ทั้ง Oracle และ SQL Server FTS สนับสนุนคำหลัก CONTAINS แต่ไวยากรณ์ยังคงแตกต่างกันเล็กน้อย:

ออราเคิล:

WHERE CONTAINS(t.something, 'bla OR foo OR batz', 1) > 0

เซิร์ฟเวอร์ SQL:

WHERE CONTAINS(t.something, '"bla*" OR "foo*" OR "batz*"')

คอลัมน์ที่คุณกำลังสืบค้นจะต้องจัดทำดัชนีข้อความแบบเต็ม

อ้างอิง:


11
สวัสดีด้วย Oracle คุณต้องสร้างดัชนีข้อความธรรมดาในคอลัมน์ที่คุณต้องการใช้ตัวดำเนินการ "CONTAINS" ทั้งนี้ขึ้นอยู่กับปริมาณข้อมูลของคุณซึ่งอาจนานมาก
Pierre-Gilles Levallois

18
ด้วย SQL Server (อย่างน้อยรุ่น 2008) ความคิดเห็นของ @Pilooz ก็มีผลเช่นกันคุณต้องสร้างดัชนีข้อความแบบเต็ม
Marcel

ความยาวสูงสุดคือ 4000
ᴍᴀᴛᴛʙᴀᴋᴇʀ

59

หากคุณต้องการให้งบของคุณอ่านง่ายคุณสามารถใช้ REGEXP_LIKE (มีให้ตั้งแต่รุ่น Oracle 10 เป็นต้นไป)

ตารางตัวอย่าง:

SQL> create table mytable (something)
  2  as
  3  select 'blabla' from dual union all
  4  select 'notbla' from dual union all
  5  select 'ofooof' from dual union all
  6  select 'ofofof' from dual union all
  7  select 'batzzz' from dual
  8  /

Table created.

ไวยากรณ์ดั้งเดิม:

SQL> select something
  2    from mytable
  3   where something like 'bla%'
  4      or something like '%foo%'
  5      or something like 'batz%'
  6  /

SOMETH
------
blabla
ofooof
batzzz

3 rows selected.

และข้อความค้นหาที่เรียบง่ายด้วย REGEXP_LIKE

SQL> select something
  2    from mytable
  3   where regexp_like (something,'^bla|foo|^batz')
  4  /

SOMETH
------
blabla
ofooof
batzzz

3 rows selected.

แต่ ...

ฉันจะไม่แนะนำตัวเองเนื่องจากประสิทธิภาพไม่ค่อยดี ฉันจะใช้เพรดิเคต LIKE หลายอัน ตัวอย่างเป็นเพียงเพื่อความสนุกสนาน


4
+1 ภาพประกอบที่ดีของการใช้งาน REGEXP ใน 10 กรัม ฉันอยากรู้ว่าถ้าการแสดงจะยิ่งแย่ไปกว่านั้นจริง ๆ ทั้งสองจะต้องใช้การสแกนแบบเต็มตารางและ / หรือดัชนีใช่หรือไม่
DCookie

12
จริง แต่นิพจน์ทั่วไปจะเผาซีพียูอย่างบ้าคลั่งไม่ใช่ I / O ถ้ามันแย่ลงและยิ่งแย่แค่ไหนขึ้นอยู่กับว่ารายการของคุณมีขนาดใหญ่แค่ไหนและคอลัมน์นั้นถูกจัดทำดัชนีหรือไม่ มันเป็นเพียงคำเตือนเพื่อให้โปสเตอร์ต้นฉบับไม่แปลกใจเมื่อเขาเริ่มใช้มัน
Rob van Wijk

49

คุณติดอยู่กับ

WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'

นอกเสียจากคุณจะเติมตารางชั่วคราว (รวมไวด์การ์ดไว้ในข้อมูล) และเข้าร่วมดังนี้:

FROM YourTable                y
    INNER JOIN YourTempTable  t On y.something LIKE t.something

ลองใช้ (ใช้ไวยากรณ์ SQL Server):

declare @x table (x varchar(10))
declare @y table (y varchar(10))

insert @x values ('abcdefg')
insert @x values ('abc')
insert @x values ('mnop')

insert @y values ('%abc%')
insert @y values ('%b%')

select distinct *
FROM @x x
WHERE x.x LIKE '%abc%' 
   or x.x LIKE '%b%'


select distinct x.*  
FROM @x             x
    INNER JOIN  @y  y On x.x LIKE y.y

เอาท์พุท:

x
----------
abcdefg
abc

(2 row(s) affected)

x
----------
abc
abcdefg

(2 row(s) affected)

ตกลงนี้จะทำงาน แต่ก็ไม่ได้ไปลงในทิศทางที่ฉันตั้งใจในการทำคำสั่ง SQL ได้ง่ายขึ้นอ่าน :)
selfawaresoup

10
ใน SQL คุณใช้การใช้ดัชนีและประสิทธิภาพ ใช้การเยื้องและการตั้งชื่อสำหรับความสามารถในการอ่าน SQL เท่านั้นเมื่อคุณทำการแก้ไขอื่น ๆ เพื่อความสามารถในการอ่านเท่านั้นคุณเสี่ยงต่อการเปลี่ยนแผนการดำเนินการ (ซึ่งมีผลต่อการใช้ดัชนีและประสิทธิภาพ) หากคุณไม่ระวังคุณสามารถเปลี่ยนคิวรีที่ใช้งานได้ทันทีให้เป็นคิวรีที่ช้ามากโดยทำการเปลี่ยนแปลงเล็กน้อย
กม.

คำสั่งแรกของคำตอบนี้คือกุญแจสำคัญ - (มากที่สุด) ระบบและภาษาที่ใช้ SQL ไม่สนับสนุนสิ่งที่คุณต้องการไม่ใช่โดยไม่ต้องใช้งานแก้ไข (ในเซิร์ฟเวอร์ SQL การทำดัชนีข้อความแบบเต็มจะช่วยได้ไหม)
Philip Kelley

@Philip Kelley การจัดทำดัชนีข้อความแบบเต็มของ SQL Server สามารถทำได้LIKE 'bla%' ซึ่งในรหัสตัวอย่างของ OP หรือไม่ หรือจะLIKE '%bla%'ค้นหาได้ใน
กม.

ฉันไม่รู้จริงๆว่าฉันไม่เคยใช้ดัชนี FT ฉันโยนมันเป็นตัวอย่างของการแก้ไขที่เป็นไปได้ที่รวมอยู่ในผลิตภัณฑ์แล้ว สำหรับสิ่งที่เขาทำ (A หรือ B หรือ C) ฉันสงสัยว่ามันไม่ได้ทำมีความมั่นใจพอสมควรว่าจะใช้ความพยายามอย่างมากในการพิจารณาเรื่องนี้และรู้ว่าอยู่นอกขอบเขตของคำถามเดิมของเขา (ไม่ SQL ทำได้โดยกำเนิด)
Philip Kelley

20

ด้วย PostgreSQL มีรูปแบบANYหรือALL:

WHERE col LIKE ANY( subselect )

หรือ

WHERE col LIKE ALL( subselect )

โดยที่การเลือกย่อยส่งคืนข้อมูลหนึ่งคอลัมน์


1
มีLIKE ANYและLIKE ALLร่วมกันกับทุกภาษา SQL คือส่วนหนึ่งของภาษาหลักหรือเฉพาะเจาะจงกับภาษาหรือไม่?
Assad Ebrahim

1
@ AssadEbrahim ไม่เฉพาะเจาะจง Oracle มี= ANYหรือ<> ALLใช้งานได้เฉพาะใน SQL เท่านั้นไม่ใช่ใน PLSQL
เบอนัวต์

ฉันคิดว่านี่เป็นรูปแบบมาตรฐาน (แต่มีไม่กี่ DBMS ที่นำมาใช้)
2017

สำหรับ postgres ดูstackoverflow.com/questions/2245536/…
rogerdpack

13

โซลูชันอื่นควรทำงานกับ RDBMS ใด ๆ :

WHERE EXISTS (SELECT 1
                FROM (SELECT 'bla%' pattern FROM dual UNION ALL
                      SELECT '%foo%'        FROM dual UNION ALL
                      SELECT 'batz%'        FROM dual)
               WHERE something LIKE pattern)

1
แต่มันน่าเกลียดกว่าชุดคำสั่ง OR หรือ
Fandango68

1
@ Fandango68 แต่สหภาพเลือกจะถูกแทนที่โดยแหล่งที่มาอีกรูปแบบเช่นโต๊ะ, มุมมอง ฯลฯ
MIK

10

ฉันอยากจะแนะนำให้ใช้ฟังก์ชั่นผู้ใช้ TableValue หากคุณต้องการสรุปเทคนิค Inner Join หรือ temp table ตามที่แสดงไว้ด้านบน นี่จะช่วยให้อ่านได้ชัดเจนขึ้น

หลังจากใช้ฟังก์ชั่นแยกที่กำหนดไว้ที่: http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx

เราสามารถเขียนสิ่งต่อไปนี้ตามตารางที่ฉันสร้างขึ้นเรียกว่า "ปลา" (int id, varchar (50) ชื่อ)

SELECT Fish.* from Fish 
    JOIN dbo.Split('%ass,%e%',',') as Splits 
    on Name like Splits.items  //items is the name of the output column from the split function.

เอาท์พุท

1 เบส
2 Pike
7 คนตกปลา
8 วอลลี่

1
แถวจะซ้ำกันหากจับคู่ตามเงื่อนไขหลายข้อในครั้งเดียว
มิค

7

วิธีหนึ่งคือการจัดเก็บเงื่อนไขในตาราง temp (หรือตัวแปรตารางใน SQL Server) และเข้าร่วมกับสิ่งนี้:

SELECT t.SomeField
FROM YourTable t
   JOIN #TempTableWithConditions c ON t.something LIKE c.ConditionValue

แถวจะซ้ำกันหากจับคู่ตามเงื่อนไขหลายข้อในครั้งเดียว
มิค

7

ใช้การรวมภายในแทน:

SELECT ...
FROM SomeTable
JOIN
(SELECT 'bla%' AS Pattern 
UNION ALL SELECT '%foo%'
UNION ALL SELECT 'batz%'
UNION ALL SELECT 'abc'
) AS Patterns
ON SomeTable.SomeColumn LIKE Patterns.Pattern

1
นั่นคือสิ่งที่ฉันต้องการหลีกเลี่ยง แม้ว่ามันจะใช้งานได้
selfawaresoup

ทำไมหลีกเลี่ยงการแก้ปัญหานี้? มันทำงานได้เร็วเท่ากับโซลูชันที่ได้รับการยอมรับและมีความหลากหลาย
Phil Factor

3
@PhilFactor โซลูชันนี้สามารถสร้างแถวที่ซ้ำกัน
Jakub Kania

5

ฉันทำงานกับ SQl Server และ Oracle ที่นี่ แต่ฉันสนใจถ้าเป็นไปได้ใน RDBMS ใด ๆ เลย

Teradata รองรับไวยากรณ์LIKE ALL / ANY :

ALL สตริงในทุกรายการ
ใด ใดสตริงในรายการ

┌──────────────────────────────┬────────────────────────────────────┐
      THIS expression         IS equivalent to this expression  
├──────────────────────────────┼────────────────────────────────────┤
 x LIKE ALL ('A%','%B','%C%')  x LIKE 'A%'                        
                               AND x LIKE '%B'                    
                               AND x LIKE '%C%'                   
                                                                  
 x LIKE ANY ('A%','%B','%C%')  x LIKE 'A%'                        
                               OR x LIKE '%B'                     
                               OR x LIKE '%C%'                    
└──────────────────────────────┴────────────────────────────────────┘

แก้ไข:

jOOQ เวอร์ชั่น 3.12.0 รองรับไวยากรณ์นั้น:

เพิ่มใยสังเคราะห์ [ไม่ใช่] ชอบอะไรก็ได้และ [ไม่] ชอบตัวดำเนินการทั้งหมด

หลายครั้งผู้ใช้ SQL ต้องการให้สามารถรวม LIKE และเพรดิเคตได้ดังเช่น

SELECT *
FROM customer
WHERE last_name [ NOT ] LIKE ANY ('A%', 'E%') [ ESCAPE '!' ]

วิธีแก้ไขคือขยายเพรดิเคตด้วยตนเองให้เท่ากัน

SELECT *
FROM customer
WHERE last_name LIKE 'A%'
OR last_name LIKE 'E%'

jOOQ สามารถรองรับเพรดิเคตสังเคราะห์ได้นอกกรอบ


PostgreSQL LIKE/ILIKE ANY (ARRAY[]):

SELECT *
FROM t
WHERE c LIKE ANY (ARRAY['A%', '%B']);

SELECT *
FROM t
WHERE c LIKE ANY ('{"Do%", "%at"}');

db <> การสาธิตซอ


เกล็ดหิมะยังรองรับLIKE ANY / LIKE ALL ที่ตรงกันทั้งหมด :

ชอบอะไรก็ได้

อนุญาตการจับคู่สตริงตามการเปรียบเทียบด้วยตัวพิมพ์เล็กและตัวพิมพ์ใหญ่

<subject> LIKE ANY (<pattern1> [, <pattern2> ... ] ) [ ESCAPE <escape_char> ]

ตัวอย่าง:

SELECT * 
FROM like_example 
WHERE subject LIKE ANY ('%Jo%oe%','T%e')
-- WHERE subject LIKE ALL ('%Jo%oe%','J%e')

4

คุณสามารถลองสิ่งนี้ได้

ฟังก์ชัน

CREATE  FUNCTION [dbo].[fn_Split](@text varchar(8000), @delimiter varchar(20))
RETURNS @Strings TABLE
(   
  position int IDENTITY PRIMARY KEY,
  value varchar(8000)  
)
AS
BEGIN

DECLARE @index int
SET @index = -1

WHILE (LEN(@text) > 0)
  BEGIN 
    SET @index = CHARINDEX(@delimiter , @text) 
    IF (@index = 0) AND (LEN(@text) > 0) 
      BEGIN  
        INSERT INTO @Strings VALUES (@text)
          BREAK 
      END 
    IF (@index > 1) 
      BEGIN  
        INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))  
        SET @text = RIGHT(@text, (LEN(@text) - @index)) 
      END 
    ELSE
      SET @text = RIGHT(@text, (LEN(@text) - @index))
    END
  RETURN
END

สอบถาม

select * from my_table inner join (select value from fn_split('ABC,MOP',','))
as split_table on my_table.column_name like '%'+split_table.value+'%';

4

ฉันมีวิธีแก้ปัญหาง่าย ๆ ที่ทำงานในpostgresql เป็นอย่างน้อยโดยใช้like anyตามด้วยรายการ regex นี่คือตัวอย่างดูที่การระบุยาปฏิชีวนะบางอย่างในรายการ:

select *
from database.table
where lower(drug_name) like any ('{%cillin%,%cyclin%,%xacin%,%mycine%,%cephal%}')

3

ฉันยังสงสัยในสิ่งเช่นนั้น ฉันเพียงแค่การทดสอบโดยใช้การรวมกันของSUBSTRINGและINและมันก็เป็นวิธีการแก้ปัญหาที่มีประสิทธิภาพสำหรับชนิดของปัญหานี้ ลองใช้แบบสอบถามด้านล่าง:

Select * from TB_YOUR T1 Where SUBSTRING(T1.Something, 1,3) IN ('bla', 'foo', 'batz')

1
ปัญหาหนึ่งของวิธีนี้คือคุณสูญเสียความสามารถในการใช้ดัชนีใน t1.something หากมีอยู่ ..
ShoeLace

1
สิ่งนี้จะไม่พบ 'batz'
mik

3

ในOracleคุณสามารถใช้คอลเล็กชันด้วยวิธีต่อไปนี้:

WHERE EXISTS (SELECT 1
                FROM TABLE(ku$_vcnt('bla%', '%foo%', 'batz%'))
               WHERE something LIKE column_value)

ที่นี่ฉันใช้ประเภทคอลเลกชันที่กำหนดไว้ล่วงหน้าku$_vcntแต่คุณสามารถประกาศประเภทของคุณเองเช่นนี้:

CREATE TYPE my_collection AS TABLE OF VARCHAR2(4000);

2

สำหรับ SQL Server คุณสามารถใช้งาน Dynamic SQL ได้

เวลาส่วนใหญ่ในสถานการณ์เช่นนี้คุณมีพารามิเตอร์ของส่วนคำสั่ง IN ขึ้นอยู่กับข้อมูลบางส่วนจากฐานข้อมูล

ตัวอย่างด้านล่างเป็น "บังคับ" เพียงเล็กน้อย แต่สามารถจับคู่กรณีจริงต่างๆที่พบในฐานข้อมูลดั้งเดิม

สมมติว่าคุณมีตารางบุคคลที่ชื่อบุคคลถูกเก็บไว้ในเขตข้อมูลPersonNameเดียวเป็น FirstName + '' + LastName คุณต้องเลือกบุคคลทั้งหมดจากรายการชื่อที่เก็บไว้ในฟิลด์NameToSelectในตารางNamesToSelectรวมถึงเกณฑ์เพิ่มเติมบางอย่าง (เช่นกรองตามเพศวันเกิด ฯลฯ )

คุณสามารถทำได้ดังนี้

-- @gender is nchar(1), @birthDate is date 

declare 
  @sql nvarchar(MAX),
  @subWhere nvarchar(MAX)
  @params nvarchar(MAX)

-- prepare the where sub-clause to cover LIKE IN (...)
-- it will actually generate where clause PersonName Like 'param1%' or PersonName Like 'param2%' or ...   
set @subWhere = STUFF(
  (
    SELECT ' OR PersonName like ''' + [NameToSelect] + '%''' 
        FROM [NamesToSelect] t FOR XML PATH('')
  ), 1, 4, '')

-- create the dynamic SQL
set @sql ='select 
      PersonName
      ,Gender
      ,BirstDate    -- and other field here         
  from [Persons]
  where 
    Gender = @gender
    AND BirthDate = @birthDate
    AND (' + @subWhere + ')'

set @params = ' @gender nchar(1),
  @birthDate Date'     

EXECUTE sp_executesql @sql, @params,    
  @gender,  
  @birthDate

2

ฉันอาจมีทางออกสำหรับสิ่งนี้ถึงแม้ว่ามันจะใช้ได้เฉพาะใน SQL Server 2008 เท่าที่ฉันรู้ ฉันค้นพบว่าคุณสามารถใช้ตัวสร้างแถวที่อธิบายไว้ในhttps://stackoverflow.com/a/7285095/894974เพื่อเข้าร่วมตาราง 'ตัวละคร' โดยใช้ประโยคคล้ายกัน มันฟังดูซับซ้อนกว่านี้แล้วดู:

SELECT [name]
  ,[userID]
  ,[name]
  ,[town]
  ,[email]
FROM usr
join (values ('hotmail'),('gmail'),('live')) as myTable(myColumn) on email like '%'+myTable.myColumn+'%' 

ซึ่งจะส่งผลให้ผู้ใช้ทั้งหมดที่มีที่อยู่อีเมลเหมือนที่อยู่ในรายการ หวังว่ามันจะใช้กับทุกคน ปัญหาได้รบกวนฉันมาระยะหนึ่งแล้ว


1
นั่นดูน่าสนใจ. อย่างไรก็ตามโปรดทราบว่าสิ่งนี้ควรใช้กับตาราง smal เท่านั้นเนื่องจากคำสั่ง like ไม่สามารถใช้ดัชนีได้ นี่คือเหตุผลที่การค้นหาข้อความแบบเต็มในขณะที่ตั้งค่าได้ยากขึ้นเป็นตัวเลือกที่ดีกว่าถ้าคุณมีข้อมูลจำนวนมาก
HLGEM

2

เริ่มต้นด้วย 2016 SQL Server รวมถึงฟังก์ชั่นSTRING_SPLIT ฉันใช้ SQL Server v17.4 และฉันได้รับสิ่งนี้สำหรับฉัน:

DECLARE @dashboard nvarchar(50)
SET @dashboard = 'P1%,P7%'

SELECT * from Project p
JOIN STRING_SPLIT(@dashboard, ',') AS sp ON p.ProjectNumber LIKE sp.value


1

ใช้งานได้กับค่าที่คั่นด้วยเครื่องหมายจุลภาค

DECLARE @ARC_CHECKNUM VARCHAR(MAX)
SET @ARC_CHECKNUM = 'ABC,135,MED,ASFSDFSF,AXX'
SELECT ' AND (a.arc_checknum LIKE ''%' + REPLACE(@arc_checknum,',','%'' OR a.arc_checknum LIKE ''%') + '%'')''

ประเมินเป็น:

 AND (a.arc_checknum LIKE '%ABC%' OR a.arc_checknum LIKE '%135%' OR a.arc_checknum LIKE '%MED%' OR a.arc_checknum LIKE '%ASFSDFSF%' OR a.arc_checknum LIKE '%AXX%')

หากคุณต้องการให้ใช้ดัชนีคุณต้องละเว้น'%'อักขระตัวแรก


1

ใน Oracle RBDMS คุณสามารถบรรลุพฤติกรรมนี้โดยใช้ฟังก์ชันREGEXP_LIKE

รหัสต่อไปนี้จะทดสอบว่าสตริงที่สามมีอยู่ในรายการนิพจน์หนึ่ง | สอง | สาม | สี่ | ห้า (ซึ่งสัญลักษณ์ " | " หมายถึงการดำเนินการตรรกะหรือ)

SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('three', 'one|two|three|four|five');

RESULT
---------------------------------
Success !!!

1 row selected.

การแสดงออกก่อนหน้าเทียบเท่ากับ:

three=one OR three=two OR three=three OR three=four OR three=five

ดังนั้นมันจะประสบความสำเร็จ

ในทางกลับกันการทดสอบต่อไปนี้จะล้มเหลว

SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('ten', 'one|two|three|four|five');

no rows selected

มีฟังก์ชันหลายอย่างที่เกี่ยวข้องกับนิพจน์ทั่วไป (REGEXP_ *) ที่มีอยู่ใน Oracle ตั้งแต่รุ่น 10g หากคุณเป็นนักพัฒนา Oracle และสนใจหัวข้อนี้นี้ควรจะเป็นจุดเริ่มต้นที่ดีการใช้นิพจน์ทั่วไปกับ Oracle Database


1

อาจเป็นเพราะคุณคิดว่าชุดค่าผสมนี้:

SELECT  * 
FROM    table t INNER JOIN
(
  SELECT * FROM (VALUES('bla'),('foo'),('batz')) AS list(col)
) l ON t.column  LIKE '%'+l.Col+'%'

หากคุณได้กำหนดดัชนีข้อความแบบเต็มสำหรับตารางเป้าหมายแล้วคุณสามารถใช้ทางเลือกนี้:

SELECT  * 
FROM    table t
WHERE CONTAINS(t.column, '"bla*" OR "foo*" OR "batz*"')

ขอบคุณ. นี่ควรเป็นคำตอบที่ IMO ยอมรับ ไม่ใช่ทุกคนที่มีดัชนีข้อความแบบเต็มที่กำหนดไว้ (สิ่งใดก็ตามที่มีความหมาย) คำแนะนำแรกของคุณทำงานได้อย่างมีเสน่ห์ คุณสามารถใส่สัญลักษณ์แทนลงในค่า temp table แทนการต่อเชื่อมกับ LIKE
คนโง่


0

ใน Teradata LIKE ANY ('%ABC%','%PQR%','%XYZ%')คุณสามารถใช้ ด้านล่างเป็นตัวอย่างที่ให้ผลลัพธ์ที่เหมือนกันสำหรับฉัน

--===========
--  CHECK ONE
--===========
SELECT *
FROM Random_Table A
WHERE (Lower(A.TRAN_1_DSC) LIKE ('%american%express%centurion%bank%')
OR Lower(A.TRAN_1_DSC) LIKE ('%bofi%federal%bank%')
OR Lower(A.TRAN_1_DSC) LIKE ('%american%express%bank%fsb%'))

;
--===========
--  CHECK TWO
--===========
SELECT *
FROM Random_Table  A
WHERE Lower(A.TRAN_1_DSC) LIKE ANY 
('%american%express%centurion%bank%',
'%bofi%federal%bank%',
'%american%express%bank%fsb%')

0

ฉันรู้ว่ามันสายมาก แต่ฉันก็มีสถานการณ์ที่คล้ายกัน ฉันต้องการตัวดำเนินการ "Like In" สำหรับชุดของโพรซีเดอร์ที่เก็บไว้ซึ่งยอมรับพารามิเตอร์จำนวนมากและจากนั้นใช้พารามิเตอร์เหล่านั้นเพื่อรวบรวมข้อมูลจากระบบ RDBMS หลายระบบดังนั้นจึงไม่มีเทคนิคเฉพาะของ RDBMS แต่ขั้นตอนการจัดเก็บและฟังก์ชั่นใด ๆ จะทำงานบน MS SQL Server ดังนั้นเราจึงสามารถใช้ T-SQL สำหรับการทำงานของการสร้างคำสั่ง SQL แบบเต็มสำหรับแต่ละ RDBMS แต่ผลลัพธ์นั้นจะต้องเป็นอิสระจาก RDBMS

นี่คือสิ่งที่ฉันเกิดขึ้นในขณะนี้เพื่อเปลี่ยนสตริงที่มีการคั่น (เช่นพารามิเตอร์ที่เข้ามาในกระบวนงานที่เก็บไว้) เป็นบล็อกของ SQL ฉันเรียกมันว่า "ไลเคน" สำหรับ "ไลค์อิน" รับมัน

Lichen.sql

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =======================================================================
-- Lichen - Scalar Valued Function
-- Returns nvarchar(512) of "LIKE IN" results.  See further documentation.
-- CREATOR: Norman David Cooke
-- CREATED: 2020-02-05
-- UPDATED:
-- =======================================================================
CREATE OR ALTER FUNCTION Lichen 
(
    -- Add the parameters for the function here
    @leadingAnd bit = 1,
    @delimiter nchar(1) = ';',
    @colIdentifier nvarchar(64),
    @argString nvarchar(256)
)
RETURNS nvarchar(512)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @result nvarchar(512)

    -- set delimiter to detect (add more here to detect a delimiter if one isn't provided)
    DECLARE @delimit nchar(1) = ';'
    IF NOT @delimiter = @delimit 
        SET @delimit = @delimiter


    -- check to see if we have any delimiters in the input pattern
    IF CHARINDEX(@delimit, @argString) > 1  -- check for the like in delimiter
    BEGIN  -- begin 'like in' branch having found a delimiter
        -- set up a table variable and string_split the provided pattern into it.
        DECLARE @lichenTable TABLE ([id] [int] IDENTITY(1,1) NOT NULL, line NVARCHAR(32))
        INSERT INTO @lichenTable SELECT * FROM STRING_SPLIT(@argString, ';')

        -- setup loop iterators and determine how many rows were inserted into lichen table
        DECLARE @loopCount int = 1
        DECLARE @lineCount int 
        SELECT @lineCount = COUNT(*) from @lichenTable

        -- select the temp table (to see whats inside for debug)
        --select * from @lichenTable

        -- BEGIN AND wrapper block for 'LIKE IN' if bit is set
        IF @leadingAnd = 1
            SET @result = ' AND ('
        ELSE
            SET @result = ' ('

        -- loop through temp table to build multiple "LIKE 'x' OR" blocks inside the outer AND wrapper block
        WHILE ((@loopCount IS NOT NULL) AND (@loopCount <= @lineCount))
        BEGIN -- begin loop through @lichenTable
            IF (@loopcount = 1) -- the first loop does not get the OR in front
                SELECT @result = CONCAT(@result, ' ', @colIdentifier, ' LIKE ''', line, '''') FROM @lichenTable WHERE id = @loopCount
            ELSE  -- but all subsequent loops do
                SELECT @result = CONCAT(@result, ' OR ', @colIdentifier, ' LIKE ''', line, '''') FROM @lichenTable WHERE id = @loopCount
            SET @loopcount = @loopCount + 1     -- increment loop
        END -- end loop through @lichenTable

        -- set final parens after lichenTable loop
        SET @result = CONCAT(@result, ' )')
    END  -- end 'like in' branch having found a delimiter
    ELSE -- no delimiter was provided
    BEGIN   -- begin "no delimiter found" branch
        IF @leadingAnd = 1 
            SET @result = CONCAT(' AND ', @colIdentifier, ' LIKE ''' + @argString + '''')
        ELSE
            SET @result = CONCAT(' ', @colIdentifier, ' LIKE ''' + @argString + '''')
    END     -- end "no delimiter found" branch

    -- Return the result of the function
    RETURN @result
END  -- end lichen function

GO

อาจมีการวางแผนการตรวจจับตัวคั่น แต่ในตอนนี้มันจะมีค่าเริ่มต้นเป็นเครื่องหมายอัฒภาคเพื่อให้คุณใส่defaultเข้าไปได้ อาจมีข้อบกพร่องในเรื่องนี้ @leadingAndพารามิเตอร์เป็นเพียงค่าบิตเพื่อตรวจสอบว่าคุณต้องการนำ "และ" ใส่ในหน้าของบล็อกจึงเหมาะกับในอย่างกับที่อื่น ๆ ที่เพิ่มเติมข้อ

ตัวอย่างการใช้งาน (พร้อมตัวคั่นใน argString)

SELECT [dbo].[Lichen] (
   default        -- @leadingAND, bit, default: 1
  ,default        -- @delimiter, nchar(1), default: ';'
  ,'foo.bar'      -- @colIdentifier, nvarchar(64), this is the column identifier
  ,'01%;02%;%03%' -- @argString, nvarchar(256), this is the input string to parse "LIKE IN" from
)
GO

จะส่งคืน nvarchar (512) ที่มี:

 AND ( foo.bar LIKE '01%' OR foo.bar LIKE '02%' OR foo.bar LIKE '%03%' ) 

นอกจากนี้ยังจะข้ามบล็อกหากอินพุตไม่มีตัวคั่น:

ตัวอย่างการใช้งาน (ไม่มีตัวคั่นใน argString)

SELECT [dbo].[Lichen] (
   default        -- @leadingAND, bit, default: 1
  ,default        -- @delimiter, nchar(1), default: ';'
  ,'foo.bar'      -- @colIdentifier, nvarchar(64), this is the column identifier
  ,'01%'          -- @argString, nvarchar(256), this is the input string to parse "LIKE IN" from
)
GO

จะส่งคืน nvarchar (512) ที่มี:

 AND foo.bar LIKE '01%'

ฉันจะทำงานนี้ต่อไปดังนั้นหากฉันมองข้ามบางสิ่งบางอย่าง (แจ่มแจ้งชัดเจนหรืออย่างอื่น) โปรดแสดงความคิดเห็นหรือติดต่อ


-3

ทำเช่นนี้

WHERE something + '%' in ('bla', 'foo', 'batz')
OR '%' + something + '%' in ('tra', 'la', 'la')

หรือ

WHERE something + '%' in (select col from table where ....)

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