2016-04-26 31 views
-1

我想檢索每行中字母數量差異的列。例如列中差異的數量

如果你有一個值「測試」,而另一行有一個值「測試」,那麼差異是「測試」和「測試」之間的4個字母。列的數據將是值4

I have reflected about it and I don't know where to begin 

id || value  || category || differences 
-------------------------------------------------- 
1 || test  || 1   || 4 
2 || testing || 1   || null 
11 || candy  || 2   || -3  
12 || ca  || 2   || null  

在這種情況下,「測試」和「休息」之間沒有區別。

+0

對於ID 1,你的差異不是3,ID 11是-3? –

+0

'test'和'rest'之間沒有區別嗎? –

+0

你在id 2有一個空白區域,是的你的權利它應該是-3在id 11.我的不好 – KLN

回答

2

我想你正在尋找的是edit difference的措施,而不是僅僅計數前綴相似性,其中有幾個常見的算法。 Levenshtein's method是我之前使用過的,我已經看到它作爲TSQL函數實現。對this SO question的回答建議您在TSQL中實現幾個實現,您可能只需按原樣進行操作即可使用。

(雖然需要時間來測試代碼並理解方法,而不是僅僅複製代碼並使用它,以便在出現錯誤時可以理解輸出 - 否則您可能會創建一些技術債務以後必須還款)

確切地說,你想要的距離計算方法取決於你想要如何計算某些東西,例如你是否將替換計爲一個變更或刪除和插入,如果你想要考慮子串移動等等,你的字符串足夠長。

0

我覺得你只是想len()lead()

select t.id, t.value, t.category, 
     (len(lead(value) over (partition by t.category order by t.id) - 
     len(value) 
     ) as difference 
from t; 
-1

你也可以使用自加盟查詢象下面這樣:

--create table tbl (id int, value nvarchar(100), category int); 
--insert into tbl values 
--(1,N'test',1) 
--,(2,N' testing',1) 
--,(11,N'candy',2)  
--,(12,N'ca',2); 
select A.*, LEN(B.value)-LEN(A.value) as difference 
from tbl A LEFT JOIN tbl B on A.id +1 =B.id and A.category=B.category 
--drop table tbl 

更新:我注意到,你奇怪定位的空間最後。在計算長度時,大多數SQL服務器不會計算結尾空格。因此,這裏是對上面的查詢黑客

select A.*, LEN(B.value+'>')-LEN(A.value+'>') as difference 
from tbl A LEFT JOIN tbl B on A.id +1 =B.id and A.category=B.category 

正如在評論中指出,該標識的可能不會是連續的,在這種情況下 試試這個:

create table #temp (rownum int PRIMARY KEY IDENTITY(1,1), id int, value nvarchar(100), category int) 
insert into #temp (id, value, category) 
select id, value, category from tbl order by id asc 


    select A.id, A.value, A.category, LEN(B.value+'>')-LEN(A.value+'>') as difference 
    from #temp A LEFT JOIN #temp B on A.rownum +1 =B.rownum and A.category=B.category 
+0

哦,有趣的是,SQL Server不計算尾隨空白。我不知道。這是這方面最有價值的信息。您的查詢假定ID是連續的。但是,在使用ID時最好不要做出這樣的假設。 –

0
create table #temp 
(
id int, 
value varchar(30), 
category int 
) 

insert into #temp 
select 1,'test',1 
union all 
select 2,'testing',1 
union all 
select 1,'Candy',2 
union all 
select 2,'Ca',2 

;with cte 
as 
(
select id,value,category,lead(value) over (partition by category order by id) as nxtvalue 
from #temp 
) 
select id,value,category,len(replace(nxtvalue,value,'')) as differences 
from cte 
+0

我試過了你的代碼,並且檢索到一條消息「關鍵字附近的語法不正確」,如果這個語句是一個公用表表達式,一個xmlnamespaces子句或一個變化跟蹤上下文子句,那麼以前的語句必須以分號結尾。 – KLN

+0

@KLN:如果消息顯示「以前的語句必須以分號結尾」,我會虛心地建議您用分號(顯然在'with'前面加一個分號)來終止前面的語句。無論如何,TheGameiswar只是以臨時表格爲例。你在用這個嗎?你沒有一個真正的*表可以使用嗎? –

+0

對不起,我沒有一個真正的表 – KLN

0

你讀了下一個記錄LEAD。然後比較與LIKE或其他字符串函數的字符串:

select 
    id, value, category, 
    case when value like next_value + '%' or next_value like value + '%' 
     then len(next_value) - len(value) 
    end as differences 
from 
(
    select id, value, category, lead(value) over (order by id) as next_value 
    from mytable 
) this_and_next; 

如果你只是想在同一類別中比較值使用分區子句:

lead(value) over (partition by category order by id) 

UPDATE:請參閱DhruvJoshi的回答SQL Server的LEN。按照我的設想,這個函數不會計算尾隨空白,所以如果你想讓它們計數的話,你需要他的技巧。這裏是LEN的文檔確認此行爲:https://technet.microsoft.com/en-us/library/ms190329(v=sql.105).aspx