2016-12-20 20 views
0

我與僱員數據庫的工作基於價值TSQL查找記錄,其中的一個字段是顯示他們所報告的管理員ID的層次,他們的指導報告等在字符串

的結構本專欄如下:

123|456|789|135|246|790 

員工經理將790,他們的經理246等,一直在鏈上。

我想找到一種方法來搜索X Manager在僱員層次結構中的記錄。

例如:SELECT FROM employees WHERE '135' IN HierachyColumn

我無法使用XML由於這之中鏈接的服務器不允許在分佈式查詢XML上。我這樣說是因爲我會用XML包裝每個值,然後使用.exist來檢查它的存在。

它自己包含此字符串的數據在VIEW之內,所以我可以根據建議對其進行一點處理,但是我在一個好方法上留下了空白。

是否有任何其他選項用於基於此字符串進行搜索?

回答

0

這應該做的伎倆:

-- sample data 
DECLARE @employees TABLE(HierarchyColumn varchar(100)) 
INSERT @employees 
VALUES ('123|456|789|135|246|790'), ('144|451|689|822'), ('144|451|689|822|990|999'); 

-- your search string 
DECLARE @searchString int = 451; 

-- solution 
SELECT * 
FROM @employees 
WHERE HierarchyColumn LIKE CONCAT('%|',@searchstring,'|%') 
OR HierarchyColumn LIKE CONCAT(@searchstring,'|%') 
OR HierarchyColumn LIKE CONCAT('%|',@searchstring); 

結果:

HierarchyColumn 
--------------------------- 
144|451|689|822 
144|451|689|822|990|999 

或者,您也可以做到這一點,將得到相同的結果:

-- sample data 
DECLARE @employees TABLE(HierarchyColumn varchar(100)) 
INSERT @employees 
VALUES ('123|456|789|135|246|790'), ('144|451|689|822'), ('144|451|689|822|990|999'); 

-- your search string 
DECLARE @searchString int = 451; 

-- solution 
SELECT HierarchyColumn 
FROM @employees 
CROSS JOIN 
(
    VALUES (CONCAT('%|',@searchstring,'|%')), 
     (CONCAT(@searchstring,'|%')), 
     (CONCAT('%|',@searchstring)) 
) p(pattern) 
WHERE HierarchyColumn LIKE pattern; 
+0

任何奇特的方式將它變成一個單一的LIKE語句,將捕獲所有3種情況?我知道它很多要問,只是好奇 – SBB

+0

''|' + HierarchyColumn +'|'如'%|' + @searchstring +'|%''。它不是[SARGABLE](https://en.wikipedia.org/wiki/Sargable),所以它不能從索引中受益。 – HABO

+0

@HABO - 這是正確的。您不會在優化器選擇的列上進行索引查找。如果你有一個SARGable的基於集合的解決方案,我很樂意看到它。;) –

0

另一種方法,提供所有層次結點的長度都是相同的,就像我這樣修改我的解決方案到this post

-- sample data 
DECLARE @employees TABLE(HierarchyColumn varchar(100)) 
INSERT @employees 
VALUES ('123|456|789|135|246|790'), ('144|451|689|822'), ('144|451|689|822|990|999'); 

-- your search string 
DECLARE @searchString int = 451; 

SELECT * 
FROM 
(
    SELECT 
    HierarchyColumn, 
    itemLevel = ROW_NUMBER() OVER (PARTITION BY e.HierarchyColumn ORDER BY N), 
    item  = SUBSTRING(e.HierarchyColumn, ((N*4)-3), 3) 
    FROM @employees e 
    CROSS APPLY 
    (
    SELECT TOP ((LEN(e.HierarchyColumn)/4)+1) ROW_NUMBER() OVER (ORDER BY (SELECT 1)) 
    FROM 
    (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) a(x), 
    (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) b(x), 
    (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) c(x), 
    (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) d(x) 
) iTally(N) 
) x 
WHERE item = @searchString; 

這不僅會返回節點,還會返回節點在層次結構中的位置級別。

HierarchyColumn   itemLevel item 
------------------------- --------- ---- 
144|451|689|822   2   451 
144|451|689|822|990|999 2   451 
2

假設(在一天結束時)您的查詢,將是非sargable。

在這樣的情況下,我傾向於選擇CharIndex()實際上可能會給你的性能提升http://cc.davelozinski.com/sql/like-vs-substring-vs-leftright-vs-charindex

Declare @Find varchar(25)='|451|' -- Note I pre-piped the Find 

Select * 
From employees 
Where CharIndex(@Find,'|'+HierarchyColumn+'|')>0 

披露:前一段時間,我跑了一系列的測試。我的結果並不像文章中列出的那麼戲劇化,但卻是值得注意的。