Sql server 在另一个字符串transact-sql中查找字符串的任何部分

Sql server 在另一个字符串transact-sql中查找字符串的任何部分,sql-server,string,tsql,Sql Server,String,Tsql,我的数据库中有表示一周中天数的字符串,如下所示: 1234567 (all days of the week) 1230567 (all days but Thursday, EU standard - day 1 is Monday) 0000067 (no day apart from Saturday and Sunday) SELECT * FROM dbo.Customers c JOIN dbo.Customers c2 ON c.CustomerNumber = c2.C

我的数据库中有表示一周中天数的字符串,如下所示:

1234567 (all days of the week)
1230567 (all days but Thursday, EU standard - day 1 is Monday)
0000067 (no day apart from Saturday and Sunday)
SELECT
    *
FROM dbo.Customers c
JOIN dbo.Customers c2 ON c.CustomerNumber = c2.CustomerNumber
    AND c.Days <> c2.Days
WHERE 1 = 1
    AND ...?
我需要写一个SQL问题来检查重叠。 例如:

1234500 and 0000067 are NOT overlapping.
while 1234500 and 0030000 are overlapping (the 3).
and 1234500 and 0000567 IS overlapping (the 5).
每个条目都有一个ID、客户编号和此工作日表示

我是这样想的:

1234567 (all days of the week)
1230567 (all days but Thursday, EU standard - day 1 is Monday)
0000067 (no day apart from Saturday and Sunday)
SELECT
    *
FROM dbo.Customers c
JOIN dbo.Customers c2 ON c.CustomerNumber = c2.CustomerNumber
    AND c.Days <> c2.Days
WHERE 1 = 1
    AND ...?
选择
*
来自dbo.c
在c.CustomerNumber=c2.CustomerNumber上加入dbo.Customers c2
c.天c2.天
其中1=1
还有。。。?
要获得两个相同客户的条目,但当我到达WHERE语句时,我遇到了一个空白。在这两个日期字段中查找子字符串(例如3)非常容易,但当7个条目中的任何一个都可能重叠时,我必须排除0(非活动日期),然后我会感到困惑


我需要一些帮助。

一种方法。逐字符匹配每一天字符串并忽略0(通过替换为不匹配的值)。下面的查询将返回同一客户没有重叠天数(忽略0)的行

SELECT
    *
FROM Customers c
JOIN Customers c2 ON c.CustomerNumber = c2.CustomerNumber
and c.days <> c2.days
where
(
REPLACE (substring (c.[days],1,1),'0','8') <> REPLACE (substring (c2.[days],1,1) ,'0','9')
AND 
REPLACE (substring (c.[days],2,1),'0','8') <> REPLACE (substring (c2.[days],2,1) ,'0','9')
AND
REPLACE (substring (c.[days],3,1),'0','8') <> REPLACE (substring (c2.[days],3,1) ,'0','9')
AND
REPLACE (substring (c.[days],4,1),'0','8') <> REPLACE (substring (c2.[days],4,1) ,'0','9')
AND 
REPLACE (substring (c.[days],5,1),'0','8') <> REPLACE (substring (c2.[days],5,1) ,'0','9')
AND
REPLACE (substring (c.[days],6,1),'0','8') <> REPLACE (substring (c2.[days],6,1) ,'0','9')
AND
REPLACE (substring (c.[days],7,1),'0','8') <> REPLACE (substring (c2.[days],7,1) ,'0','9')
)
选择
*
来自客户c
在c.CustomerNumber=c2.CustomerNumber上加入客户c2
和c.天c2.天
哪里
(
替换(子字符串(c.[days],1,1),'0','8')替换(子字符串(c2.[days],1,1),'0','9'))
及
替换(子字符串(c.[days],2,1),'0','8')替换(子字符串(c2.[days],2,1),'0','9'))
及
替换(子字符串(c.[days],3,1),'0','8')替换(子字符串(c2.[days],3,1),'0','9'))
及
替换(子字符串(c.[days],4,1),'0','8')替换(子字符串(c2.[days],4,1),'0','9'))
及
替换(子字符串(c.[days],5,1),'0','8')替换(子字符串(c2.[days],5,1),'0','9'))
及
替换(子字符串(c.[days],6,1),'0','8')替换(子字符串(c2.[days],6,1),'0','9'))
及
替换(子字符串(c.[days],7,1),'0','8')替换(子字符串(c2.[days],7,1),'0','9'))
)
使用两个,一个用于小理货表,另一个用于使用小理货表和窗口聚合函数为每个位置拆分
子字符串()。最后的
选择
显示每个重叠的

;with n as (
  select i from (values (1),(2),(3),(4),(5),(6),(7)) t(i)
)
, expand as (
  select c.CustomerNumber, c.Days, d.Day
    , cnt = count(*) over (partition by c.CustomerNumber, d.Day)
  from Customers c
    cross apply (
      select Day = substring(c.Days,n.i,1)
      from n
      ) d
  where d.Day > 0
)
select * 
from expand
where cnt > 1
rextester演示:

使用测试设置:

create table Customers (customernumber int, days char(7))
insert into Customers values 
 (1,'1234500')
,(1,'0000067') -- NOT overlapping
,(2,'1234500')
,(2,'0030000') -- IS overlapping (the 3).
,(3,'1234500')
,(3,'0000567') -- IS overlapping (the 5).
;  
返回:

+----------------+---------+-----+-----+
| CustomerNumber |  Days   | Day | cnt |
+----------------+---------+-----+-----+
|              2 | 1234500 |   3 |   2 |
|              2 | 0030000 |   3 |   2 |
|              3 | 1234500 |   5 |   2 |
|              3 | 0000567 |   5 |   2 |
+----------------+---------+-----+-----+

参考:

    • 如果没有任何DDL(底层表结构),就不可能理解要比较的数据所在的位置。也就是说,您试图做的是简单地使用

      请注意此查询:

      declare @searchstring char(7) = '1234500';
      select * from dbo.ngrams8k(@searchstring,1);
      
      返回

      position    token 
      ----------- ------
      1           1     
      2           2     
      3           3     
      4           4     
      5           5     
      6           0     
      7           0     
      
      考虑到这一点,这将帮助您:

      -- sample data
      declare @days table (daystring char(7));
      insert @days values ('0000067'),('0030000'),('0000567');
      
      declare @searchstring char(7) = '1234500';
      
      -- how to break down and compare the strings
      select 
        searchstring    = @searchstring, 
        overlapstring   = OverlapCheck.daystring,
        overlapPosition = OverlapCheck.position,
          overlapValue    = OverlapCheck.token
      from dbo.ngrams8k(@searchstring, 1) search
      join 
      (
        select * 
        from @days d
        cross apply dbo.ngrams8k(d.daystring,1)
        where token <> 0
      ) OverlapCheck on  search.position = OverlapCheck.position 
                        and search.token = OverlapCheck.token;
      

      也可能有多个重叠,我只需要知道它是否重叠,实际上我不需要知道有多少或几天重叠。按enter键太快:1234560和0234567理论上可能存在于数据库中。突然想到的坏主意:(1)将所有非零字符改为1,将二进制数字字符串转换为整数,然后(按位和)整数以检测重叠。(2) 将字符串从数字转换为XML,然后。(如果用一周位图的整数值保存一个持久的计算列,二进制方法可能不会那么糟糕。)我想到了这一点,但当我看到完成的解决方案时,我对自己说:“是的,这太难看了,一定有更好的方法”…@Glaurung先生同意,应该有更干净的方法来做到这一点。也许吧,我明天就试试。这是漫长的一天。非常感谢你的帮助!非常感谢你的帮助!非常感谢你的帮助!