2017-10-07 73 views
2

我在我的數據庫,它表示在這樣的工作日字符串:查找字符串的任何部分在另一個字符串處理SQL

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

也可能有多個重疊,我只需要確定它是否重疊,我其實不需要知道多少天或哪幾天。 –

+0

*嘆息*按下輸入太快:1234560和0234567理論上可能存在於數據庫中。 –

+0

跳躍想法的不好主意:(1)將所有非零字符更改爲1,將二進制數字字符串轉換爲整數,然後['&'](https://docs.microsoft.com/en -us/sql/t-sql/language-elements/bitwise-and-transact-sql)(按位與)整數來檢測重疊。 (2)將字符串從數字推到XML和...。 (如果持續計算的列與星期的位圖的整數值一起保存,那麼二進制方法可能不會那麼糟糕。) – HABO

回答

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') 
) 
+0

我想到了這一點,但是當我看到完成的解決方案時,我想我自己:「這是醜陋的,是更好的方式「... –

+0

@Glaurung先生同意,應該有一些更乾淨的方式來做到這一點。可能是,我明天會試一試。這是一個漫長的一天。 –

+0

非常感謝您的幫助! –

1

使用兩個common table expressions,一個用於一個微小的帳簿表,其他與cross apply()substring()用於使用所述小帳簿表與count() over()窗口聚合函數沿每個位置分裂Days通過計數每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 | 
+----------------+---------+-----+-----+ 


參見ENCE:

+0

非常感謝您的幫助! –

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 
+0

非常感謝您的幫助! –

相關問題