我的数据库中有字符串,表示一周中的天数:
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)
我需要编写一个检查重叠的SQL问题。 例如:
1234500 and 0000067 are NOT overlapping.
while 1234500 and 0030000 are overlapping (the 3).
and 1234500 and 0000567 IS overlapping (the 5).
每个条目都有一个ID,客户编号和此工作日表示。
我在想这样的事情:
SELECT
*
FROM dbo.Customers c
JOIN dbo.Customers c2 ON c.CustomerNumber = c2.CustomerNumber
AND c.Days <> c2.Days
WHERE 1 = 1
AND ...?
要获得两个同一客户的条目,但当我来到WHERE语句时,我打了一个空白。在两个Days字段中查找子字符串(例如3)非常简单,但是当7个条目中的任何一个可以重叠并且我必须排除0(非活动日)时,我会感到困惑。
我需要一些帮助。
答案 0 :(得分:1)
一种方法。每天匹配char字符串char并忽略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')
)
答案 1 :(得分:1)
使用两个common table expressions,一个用于微小的计数表,另一个用Days
分割cross apply()
和substring()
每个位置使用微小的计数表以及count() over()
窗口聚合函数,用Day
计算每个CustomerNumber
的出现次数。最终select
显示每个重叠的Day
:
;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演示:http://rextester.com/SZUANG12356
使用测试设置:
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 |
+----------------+---------+-----+-----+
<小时/> 参考:
答案 2 :(得分:1)
没有任何DDL(基础表结构),就无法理解您将要比较的数据存在的位置。也就是说,使用ngrams8k,您要做的事情很简单。
请注意此查询:
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;
返回:
searchstring overlapstring overlapPosition overlapValue
------------ ------------- -------------------- ---------------
1234500 0030000 3 3
1234500 0000567 5 5