【问题标题】:Query SQL Server with wildcard IN the database在数据库中使用通配符查询 SQL Server
【发布时间】:2016-11-30 16:09:48
【问题描述】:

我需要构建一个条件必须与数据库中的通配符匹配的查询。

举个例子就清楚了。

我有一列包含这样的字段963-4-AKS~M2RN21AXA150~~~0C1D1D~~XX~ 字符是通配符。 所以必须符合以下条件:

  • ~63-4-AKS~M
  • 963-4-AKS1M
  • 963-4-AKS~M2RN21AXA150AAA
  • 963-4-AKSAM2RN21AXA150AAA
  • 963-4-AKSCM2RN21AXA150A060C1D1DSDXX
  • 963-4-AKS~M2RN21AXA150~~~0C1D1D~~XX

我尝试了很多让我头疼的事情:(

以另一种方式(使用标准中的通配符)没问题,很容易。但是这样我就找不到钥匙了。

问题是当我在不匹配的字段中有~ 时。所以这里只有第一个和最后一个匹配以下语句:

SELECT myField FROM myTable WHERE myField LIKE REPLACE('%' + myCriteria + '%', '~', '_');

【问题讨论】:

  • ~ 替换为%
  • 你认为我为什么要写REPLACE('%' + myCriteria + '%', '~', '_')_ 是一个字符的通配符
  • 但是你说的只是第一场和最后一场比赛。所以我提供了另一种解决方案。
  • 好的,谢谢。如果您更喜欢我的问题,那么当数据库中的字段包含~ 时,条件中的任何字符都必须与之匹配。但它必须只有一个字符。或者 A%C AC 将匹配,但它不能。我需要在 A 和 C 之间留一个字符。

标签: sql sql-server wildcard


【解决方案1】:

模式和字段似乎都向左调整了。
如果确实如此,我低着头(充满悲伤),这里有一个函数。

create function is_a_match (@myField varchar(100),@myCriteria varchar(100))
returns bit
as
begin

    declare  @i                 int = 0
            ,@is_a_match        bit = 1
            ,@len_myField       int = len(@myField)
            ,@len_myCriteria    int = len(@myCriteria)
            ,@myField_c         char(1)
            ,@myCriteria_c      char(1)

    While 1=1
    begin

        set @i += 1 

        if @i > @len_myCriteria break

        if @i > @len_myField    
        begin 
            set @is_a_match = 0 
            break 
        end

        set @myField_c    = substring(@myField   ,@i,1)
        set @myCriteria_c = substring(@myCriteria,@i,1)

        if not (@myField_c = '~' or @myCriteria_c = '~' or @myField_c = @myCriteria_c) 
        begin 
            set @is_a_match = 0 
            break 
        end

    end

    return @is_a_match
end

GO

select      myCriteria
           ,dbo.is_a_match (myField,myCriteria) as is_a_match

from        (values ('~63-4-AKS~M'                          )
                   ,('963-4-AKS1M'                          )
                   ,('963-4-AKS~M2RN21AXA150AAA'            )
                   ,('963-4-AKSAM2RN21AXA150AAA'            )
                   ,('963-4-AKSCM2RN21AXA150A060C1D1DSDXX'  )
                   ,('963-4-AKS~M2RN21AXA150~~~0C1D1D~~XX'  )
                   ,('963-4-AKS~M2RN21AXA150~~~0C1X1D~~XX'  )
                   ,('963-4-AKS~M2RN21AXA150~~~0C1D1D~~XXYY')

            ) c (myCriteria)
           ,(values ('963-4-AKS~M2RN21AXA150~~~0C1D1D~~XX'  )
            ) f (myField)

+---------------------------------------+------------+
| myCriteria                            | is_a_match |
+---------------------------------------+------------+
| ~63-4-AKS~M                           | 1          |
+---------------------------------------+------------+
| 963-4-AKS1M                           | 1          |
+---------------------------------------+------------+
| 963-4-AKS~M2RN21AXA150AAA             | 1          |
+---------------------------------------+------------+
| 963-4-AKSAM2RN21AXA150AAA             | 1          |
+---------------------------------------+------------+
| 963-4-AKSCM2RN21AXA150A060C1D1DSDXX   | 1          |
+---------------------------------------+------------+
| 963-4-AKS~M2RN21AXA150~~~0C1D1D~~XX   | 1          |
+---------------------------------------+------------+
| 963-4-AKS~M2RN21AXA150~~~0C1X1D~~XX   | 0          |
+---------------------------------------+------------+
| 963-4-AKS~M2RN21AXA150~~~0C1D1D~~XXYY | 0          |
+---------------------------------------+------------+

您在字段和模式之间进行混合。
该字段可能不包含通配符。

例如 这不是匹配,因为 'A's

963-4-AKS~M2RN21AXA150~~~0C1D1D~~XX
963-4-AKSAM2RN21AXA150AAA

【讨论】:

  • 不是我,是客户。我试图解释他,但没有结果:(
  • 是的,在您的示例中,如果第一个在数据库中,则第二个必须匹配。正如我所说,其他方式没问题,但这样很难。
  • @Shadam 因为比较两侧的每个字符都可以是模式或模式的测试值,所以看起来像这样的自定义函数(或类似的逐字符逻辑)将是必需的。是的,这将是一个性能打击。你测试过这个答案吗?
  • @SlimsGhost,实际上是双倍的性能打击...在这种情况下唯一可能的 JOIN 是 LOOP JOIN...
  • @DuduMarkovitz 伙计,你完全疯了,但它确实有效!你现在和永远都是我的 SQL 英雄^^
【解决方案2】:

如果你能加强对通配符的限制,你可能会在这里有一个战斗的机会。我的意思是,如果持久数据中存在通配符,则生成有效的排列。然后使用现有查询查询排列。

但是,如果每个通配符都有 36 个可能的选项,这将变得非常痛苦。

【讨论】:

  • 这是一个 NVARCHAR(100) 字段,其中的每个 f****** 字符都可以是通配符。我的客户疯了,不明白这会如何破坏应用程序的性能。
  • 这个字符串感觉像是某种型号,这意味着在某个地方必须有一个可以限制它的主列表。我不在基地吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 2017-04-15
  • 1970-01-01
  • 2019-09-18
相关资源
最近更新 更多