SQL Server在IN语句中使用通配符

51

我认为这应该是一个基本问题,虽然我知道这个问题可能已经被问过了,但我无法找到它。我可能即将获得我的“同侪压力勋章”,但我还是要问:

在使用IN时,是否有一种我不知道的在SQL Server中使用通配符%的方法。

我意识到我可以使用OR,例如:

select *
from jobdetails
where job_no like '0711%' or job_no like '0712%'

在某些情况下,我可以使用类似于以下的子查询:

select *
from jobdetails
where job_no in (select job_no from jobs where job_id = 39)

但我想要做类似下面这样的事情:

select *
from jobdetails
where job_no in ('0711%', '0712%')
在这种情况下,百分号被视为普通字符而不是通配符,因此不返回任何行。当我需要执行此操作时,目前只是使用一堆 OR 操作符,但我知道必须有更好的方法。你用什么方法来解决这个问题?

1
如果有人来到这里,类似于后面的问题 https://dev59.com/OXA75IYBdhLWcg3w8-HZ - Mark Schultheiss
16个回答

29

如何尝试:

WHERE LEFT(job_no, 4) IN ('0711', '0712', ...)

8
我很感激你的回复,虽然这个方法可行,但可能是因为我简化了示例的缘故。我希望有一种方法不一定依赖于前四个字符,而更多地依赖于通配符。再次感谢。 - Dusty
1
这似乎是目前为止最好的答案,至少在我的情况下是如此。它将匹配列表中以指定文本开头的任何值,并且使添加条目变得更加容易(我需要一个包含100个条目的列表,因此大多数其他解决方案都太冗长了)。 - Gavin Coates

16
我认为我有一个简单的解决方案,可以满足这个问题的提出者所想要的。这对我很有效,实际上这也是我来这里的原因。我相信只需在列名周围使用括号,例如 '%text%' 结合OR即可完成。
select * from tableName
where (sameColumnName like '%findThis%' or sameColumnName like '%andThis%' or 
sameColumnName like '%thisToo%' or sameColumnName like '%andOneMore%') 

11

这个怎么样?

declare @search table
(
    searchString varchar(10)
)

-- add whatever criteria you want...
insert into @search select '0711%' union select '0712%'

select j.*
from jobdetails j
    join @search s on j.job_no like s.searchString

1
而且,就像AlexKuznetsov的回答中所述,您也可以在一个查询中完成它,而无需使用表变量或临时表。 - GalacticCowboy
这是一个有趣的方法,我之前没有想过。它可能比一堆OR运行得更快,但复制和粘贴OR可能会更快。通常只有在需要为某人生成特定报告时才会使用此方法,因此我想这样做的原因通常是为了节省打字时间。 - Dusty
最好第一条评论中有一个指向答案的链接,而不是一个(很久以后)随着时间变化而改变的参考文献。 - Mark Schultheiss

8
你可以尝试这样做:

你可以尝试像这样做:

select *
from jobdetails
where job_no like '071[12]%'

虽然不完全符合你的要求,但它有相同的效果,并且在其他方面也很灵活 :)


这非常接近我所寻找的内容。引号之间的值是否可以扩展为多个值(例如“071 [10,22]%”),您是否有详细解释的链接? - Dusty
1
@Dusty:不,'071[10,22]%将匹配任何字符串'071x%,其中x是1、0或2中的一个。不是要寻找后面跟着10或22的071。请参见模式部分:http://msdn.microsoft.com/en-us/library/ms179859.aspx - Shannon Severance
+1 虽然这不完全是我要找的,但它很接近并且有帮助。虽然这可能是最接近我所寻找的,但我无法将其标记为答案。谢谢。 - Dusty
哈哈,对不起啊。我很快就会发布一个后续问题,来定义导致我提出这个问题的问题。我想如果我能回答这个问题,我的问题就会得到解决。但还是非常感谢你的回复。 - Dusty

4
SELECT c.* FROM(
SELECT '071235' AS token UNION ALL SELECT '07113' 
 UNION ALL SELECT '071343'
UNION ALL SELECT '0713SA'
UNION ALL SELECT '071443') AS c
JOIN (
SELECT '0712%' AS pattern UNION ALL SELECT '0711%' 
 UNION ALL SELECT '071343') AS d
ON c.token LIKE d.pattern

071235
07113
071343

4

我有一个类似的目标,并采用了以下解决方案:

select *
from jobdetails as JD
where not exists ( select code from table_of_codes as TC 
                      where JD.job_no like TC.code ) 

我假设你的各种代码('0711%','0712%'等),包括%,存储在一个表中,我称之为*table_of_codes*,其中包含字段code

如果%未存储在代码表中,则只需将“%”连接起来。例如:

select *
from jobdetails as JD
where not exists ( select code from table_of_codes as TC 
                      where JD.job_no like concat(TC.code, '%') ) 

据我所知,concat()函数可能因特定数据库而异。

希望这能有所帮助。我从以下链接进行了修改:

http://us.generation-nt.com/answer/subquery-wildcards-help-199505721.html


3
  1. 我首先添加了一个全面包含通配符结果的静态表格 (这家公司使用4个字符的nvarchar代码作为它们的本地化,并通配它们的本地化) 例如,他们可能有456?这将给他们456 [1]到456 [Z],即0-9和a-z。

  2. 我必须编写一个脚本来提取当前用户(声明他们)并提取所声明用户的掩码。

  3. 创建一些临时表仅基础排名行号为此当前用户

  4. 循环遍历每个结果(YOUR或this或that等...)

  5. 插入测试表中。

以下是我使用的脚本:

Drop Table #UserMasks 
Drop Table #TESTUserMasks 

Create Table #TESTUserMasks (
    [User] [Int] NOT NULL,
    [Mask] [Nvarchar](10) NOT NULL)

Create Table #UserMasks (
    [RN] [Int] NOT NULL,
    [Mask] [Nvarchar](10) NOT NULL)

DECLARE @User INT
SET @User = 74054

Insert Into #UserMasks 
select ROW_NUMBER() OVER ( PARTITION BY ProntoUserID ORDER BY Id DESC) AS RN,
       REPLACE(mask,'?','') Mask
from dbo.Access_Masks 
where prontouserid = @User

DECLARE @TopFlag INT
SET @TopFlag = 1

WHILE (@TopFlag <=(select COUNT(*) from #UserMasks))
BEGIN
    Insert Into #TestUserMasks 
    select (@User),Code from dbo.MaskArrayLookupTable 
    where code like (select Mask + '%' from #UserMasks Where RN = @TopFlag)

    SET @TopFlag = @TopFlag + 1
END
GO

select * from #TESTUserMasks

1

IN 运算符本质上只是一种将 '=' 比较连接起来的花俏写法。实际上,它还有一个非常“本质”的特点,在 SQL 2000 中,当列表中包含约 10K 个条目时,IN 扩展为 OR 时会出现堆栈溢出错误(没错,有人会写 10k 个 IN 条目...)。所以你不能在其中使用任何通配符匹配。


1
10k个ANDs:http://support.microsoft.com/kb/224581,255个UNION ALL:http://support.microsoft.com/kb/892141。 - Remus Rusanu
我认为你现在对于“同侪压力徽章”是正确的。希望我不必担心它。 :) - Dusty

1

Jeremy Smith发表了一篇文章,我将进行概括,因为我无法回答他的特定问题。

select *
from jobdetails
where job_no like '071[1-2]%'

如果您只需要 0711%0712%,您也可以在括号内放置一个范围。对于NOT关键字,您也可以使用[^1-2]%

0
有点晚了,但你可以使用STRING_SPLIT函数。
SELECT jobdetails.* 
FROM jobdetails
CROSS APPLY  (select value 
              from STRING_SPLIT('540%,%144,orange,coconut',',') 
              WHERE jobdetails.job_no 
              like value) as leek

将其转换为可重复使用的函数并不需要太多的工作


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接