如何更新状态以匹配签名键值为星号的字符?

问题描述

我使用sql Server 2012,但遇到一个问题:我无法更新状态以匹配签名密钥带有星号*的字符。

我需要更新状态以匹配以签名密钥为例的字符

    Signature Key        Group Id   Portion Key     Status
    *$*$**s$***$**$**$*   3          12s            Match Characters

上面签名密钥中的组ID 3是** s必须等于部分密钥(12s),因此状态必须是匹配字符。

但是如果组ID值是** f且部分密钥值是15g,则它将为不匹配字符状态

因为g不等于f

Create table #Ref
(
    SignatureKey  nvarchar(50),GroupId int,PortionKey nvarchar(50),Status nvarchar(100)
)

insert into #Ref (SignatureKey,GroupId,PortionKey,status)
values ('*$*$C$***$**$**$*',3,'s',NULL),('*$*$*$FG$*$**$*',4,'F',('*$*$*$***$*$D$*',6,'D',('*$t**$*$***$***$**$*',2,'t12',('*$**$*$***$**t$**$*',5,'12t',NULL)
  
update r 
set r.Status = 'Not Match Charachters'
from #Ref r
cross apply
dbo.Split(r.SignatureKey,'$') f where CAST (r.GroupId AS INT) = f.Id and r.PortionKey <> f.Data

预期结果:

Signature Key        Group Id   Portion Key Status
*$*$C$***$**$**$*     3          s          Not Match Characters
*$*$*$FG$*$**$*       4          F          Not Match Characters
*$*$*$***$*$D$*       6          D          Not Match Characters
*$t**$*$***$***$**$*  2          t12        Match Characters
*$**$*$***$**t$**$*   5          12t        Match Characters

在签名密钥值等于部分密钥的情况下,我要说的是状态为匹配字符

恰好是(c = c)或签名密钥在组ID上都有星号,因此我将忽略开始*并进行比较

字符为(* f = 1f)的字符表示如果我有星星,则忽略与字符比较。

最后更新的帖子:

dbo.split function exist on 
https://www.sqlteam.com/forums/topic.asp?TOPIC_ID=50648

组ID也代表签名密钥中的部分编号 假设我有签名密钥;

*$*c$C$**$***$5*$6*

然后从左到右:

组ID 1值= *

组ID 2值= * c

组ID 3值= c

group id 4 value = **

群组ID 5值= ***

群组ID 6值= 5 *

群组ID 7值= 6 *

解决方法

样本数据

**$Global:MySQLConnection.Open()
$query1 = 'SELECT  *  FROM wp_woocommerce_order_items WHERE order_id = 25696 ' 
$queryResults = Invoke-MySqlQuery  -Query $query1 -Verbose
Foreach($query in $queryResults){
$listbox1.Items.Add($query)
$Global:MySQLConnection.close()
}
}**

解决方案

下面的解决方案没有采用您链接的declare @data table ( Exa int,-- example number (for result sorting purposes only) Sig nvarchar(20),-- signature key Grp int,-- group id Prt nvarchar(5) -- portion key ); insert into @data (Exa,Sig,Grp,Prt) values (1,'*$*$C$***$**$**$*',3,'s' ),(2,'*$*$*$FG$*$**$*',4,'F' ),(3,'*$*$*$***$*$D$*',6,'D' ),(4,'*$t**$*$***$***$**$*',2,'t12'),(5,'*$**$*$***$**t$**$*',5,'12t'); 函数,而是基于this StackOverflow answer来分割字符串。将答案应用于样本数据将得出:

split()

对于with cte as ( select d.Sig,1 as Starts,charindex('$',d.Sig) as Pos from @data d union all select cte.Sig,cte.Pos + 1,cte.Sig,cte.Pos + 1) from cte where Pos > 0 ) select cte.Sig,cte.Starts,cte.Pos,substring(cte.Sig,case when cte.Pos > 0 then cte.Pos - cte.Starts else len(cte.Sig) end) as Token from cte order by cte.Sig,cte.Starts; ,这将产生以下结果:

*$*$*$***$*$D$*

要在此基础上进一步建立解决方案,需要:

  1. 上述分段的行号,以检索在Sig Starts Pos Token -------------------- ----------- ----------- -------------------- *$*$*$***$*$D$* 1 2 * *$*$*$***$*$D$* 3 4 * *$*$*$***$*$D$* 5 6 * *$*$*$***$*$D$* 7 10 *** *$*$*$***$*$D$* 11 12 * *$*$*$***$*$D$* 13 14 D *$*$*$***$*$D$* 15 0 * 中指定的TokenGrp函数在这里起作用。
  2. row_number()包含通配符时,将TokenPrt匹配的方法。我使用了递归公用表表达式来拆分TokenToken来检查匹配字符的数量是否等于非通配符的数量。

这给了我

outer apply

哪个会产生:

with cte as -- recursive CTE to parse d.Sig
(
    select d.Sig,cte.Pos + 1)
    from cte
    where Pos > 0
),split as -- split cte.Sig based on parsing values
(
    select  cte.Sig,case when cte.Pos > 0 then cte.Pos - cte.Starts else len(cte.Sig) end) as Token,row_number() over(partition by cte.Sig order by cte.Starts) as Num
    from cte
),tokenW as -- recursive CTE to parse d.Prt for s.Token with wildcard
(
    select d.Sig,s.Token,1 as Pos,substring(s.Token,1,1) as PosChar
    from @data d
    join split s
        on  s.Sig = d.Sig
        and s.Num = d.Grp
    where charindex('*',s.Token) > 0
        union all
    select tw.Sig,tw.Token,tw.Pos+1,substring(tw.Token,1)
    from tokenW tw
    where tw.Pos < len(tw.Token)
)
select  d.Sig,d.Grp,d.Prt,case
            when d.Prt = s.Token then 'Match'                           -- match 100%
            when len(replace(s.Token,'*','')) = c.Cnt then 'Match'    -- match wildcard pattern
            else 'No match'
        end as [Status]
from @data d
join split s
    on  s.Sig = d.Sig
    and s.Num = d.Grp
outer apply (   select count(1) as 'Cnt' -- count number of matching characters (not counting '*')
                from tokenW tw
                join split ss
                    on  ss.Sig = tw.Sig
                    and ss.Token = tw.Token
                where tw.Sig = d.Sig
                  and tw.PosChar <> '*'
                  and tw.PosChar = substring(d.Prt,tw.Pos,1) ) c
order by d.Exa;