【问题标题】:SQL Server using wildcard within INSQL Server 在 IN 中使用通配符
【发布时间】:2009-07-02 18:58:56
【问题描述】:

因为我认为这应该是一个基本问题,所以我知道可能有人问过这个问题,但我找不到它。我可能即将获得 Peer Pressure 徽章,但我还是会问:

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

我意识到我可以使用 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,但我知道必须有更好的方法。你用什么方法?

【问题讨论】:

标签: sql sql-server wildcard in-function


【解决方案1】:

怎么样:

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

【讨论】:

  • 我很感谢您的回复,是的,这很有效,但这可能是由于我的示例的简化。我想要一些不一定依赖前 4 个字符的东西。我正在寻找更依赖通配符的东西。不过再次感谢。
  • 这似乎是迄今为止最好的答案,至少在我的情况下。这将匹配列表中以指定文本开头的任何值,并且更容易添加条目(我需要一个包含 100 个条目的列表,因此大多数其他解决方案都过于冗长)
【解决方案2】:

我想我对这个调查的发起人想要的东西有一个简单的解决方案。它对我有用,实际上这就是我来到这里开始的原因。我相信只需在列周围使用括号,如 '%text%' 并结合ORs 即可。

select * from tableName
where (sameColumnName like '%findThis%' or sameColumnName like '%andThis%' or 
sameColumnName like '%thisToo%' or sameColumnName like '%andOneMore%') 

【讨论】:

    【解决方案3】:

    这样的事情怎么样?

    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
    

    【讨论】:

    • 而且,正如 AlexKuznetsov 的回答,您也可以在没有表变量或临时表的情况下在一个查询中完成。
    • 这是一种我没有想到的有趣方法。它可能比一堆 OR 运行得更快,但它可能会更快地键入(复制和粘贴)OR。我通常只在需要为某人提供临时报告时才这样做,所以我这样做的原因通常是为了节省打字时间。
    • 更好的是,第一条评论有一个指向答案的链接,而不是随时间变化的(不久之后)参考
    【解决方案4】:

    你可以试试这样的:

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

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

    【讨论】:

    • 这非常接近我想要的。引号之间的值是否可以扩展为多个值(例如'071 [10,22]%'),您是否有详细解释这一点的链接?
    • @Dusty: 不,'071[10,22]% 将匹配任何字符串 '071x%,其中 x 是 1 0 或 2 之一。不寻找 071 后跟 10 或22. 参见模式部分:msdn.microsoft.com/en-us/library/ms179859.aspx
    • +1 虽然这不是我想要的,但它很接近并且很有帮助。虽然它可能是最接近我正在寻找的东西,但我无法准确地将其标记为答案。谢谢
    • 哈哈,对不起,伙计。我将很快发布一个后续问题,该问题定义了导致我提出这个问题的问题。我想如果我能回答这个问题,我的问题就会得到解决。再次感谢您的回复。
    【解决方案5】:
    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
    

    【讨论】:

      【解决方案6】:

      我也有类似的目标 - 并得出了这个解决方案:

      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

      【讨论】:

        【解决方案7】:
        1. 我首先添加了一个静态表,其中包含我的通配符结果的所有可能性 (这家公司有一个 4 个字符的 nvarchar 代码作为他们的地区,他们通配符他们的当地人) 即他们可能有456?这会给他们 456[1] 到 456[Z] 即 0-9 & a-z

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

        3. 创建一些临时表,只是基本的,用于对当前用户的行号进行排名

        4. 遍历每个结果(你的或这个或那个等...)

        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
        

        【讨论】:

          【解决方案8】:

          正如 Jeremy Smith 发布的那样,我会回顾一下,因为我无法回答他的那个特定问题。

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

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

          【讨论】:

            【解决方案9】:

            IN 运算符只不过是一个花哨的 OR '=' 比较。事实上,在 SQL 2000 中,当列表包含大约 10k 个条目时,由于将 IN 扩展为 ORs,因此出现了堆栈溢出错误(是的,有人编写 10k IN 条目。 ..)。所以你不能在其中使用任何通配符匹配。

            【讨论】:

            【解决方案10】:

            在 Access SQL 中,我会使用它。我想 SQLserver 具有相同的语法。

            选择 * 来自工作详情 其中job_no 像“0711*”或job_no 像“0712*”

            【讨论】:

            • 感谢您的回复,但我正在尝试找出一种在 IN 中使用通配符的方法,这样我就不必执行多个 OR。
            【解决方案11】:

            聚会有点晚了,但你可以使用 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
            

            把它变成一个可重用的函数并不需要更多的工作

            【讨论】:

              【解决方案12】:

              你的问题就在那里。使用 IN 时不能直接传递通配符。但是,您可以使用子查询。

              试试这个:

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

              我知道这看起来很疯狂,因为您可以坚持在 WHERE 子句中使用 OR。为什么是子查询?但是,当您必须匹配来自不同来源的详细信息时,子查询方法会很有用。

              拉吉

              【讨论】:

              • 为什么需要子查询,而只是将子查询或作为主查询或?
              【解决方案13】:

              试试这个

              select * 
              from jobdetails 
              where job_no between '0711' and '0713'
              

              唯一的问题是job '0713' 也将被返回 所以可以使用'07299999999999' 或添加and job_no &lt;&gt; '0713'

              丹扎米尔

              【讨论】:

              • 虽然这不能回答问题。这对我来说很有帮助,我至少可以减少查询结果的大小,然后继续使用我的客户端代码进行过滤。
              【解决方案14】:

              我只是在学习这些东西,但这有用吗?

              select *
              from jobdetails
              where job_no regexp "^(071)[1|2]";
              

              【讨论】:

                【解决方案15】:

                这可能是我最简单的解决方案使用like any

                select *
                from jobdetails
                where job_no like any ('0711%', '0712%')
                

                在 Teradata 中,这可以正常工作。

                【讨论】:

                • like any 是标准SQL 语言的一部分吗?我无法使用它。
                猜你喜欢
                • 1970-01-01
                • 2012-08-25
                • 1970-01-01
                • 1970-01-01
                • 2014-04-29
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多