2013-07-05 338 views

回答

29

創建此功能(SQLSERVER 2005+)

CREATE function [dbo].[f_split] 
(
@param nvarchar(max), 
@delimiter char(1) 
) 
returns @t table (val nvarchar(max), seq int) 
as 
begin 
set @param += @delimiter 

;with a as 
(
select cast(1 as bigint) f, charindex(@delimiter, @param) t, 1 seq 
union all 
select t + 1, charindex(@delimiter, @param, t + 1), seq + 1 
from a 
where charindex(@delimiter, @param, t + 1) > 0 
) 
insert @t 
select substring(@param, f, t - f), seq from a 
option (maxrecursion 0) 
return 
end 

使用這一說法

SELECT * 
FROM yourtable 
WHERE account in (SELECT val FROM dbo.f_split(@account, ',')) 


比較荷蘭國際集團我的分裂功能,以XML拆分:

TESTDATA:

select top 100000 cast(a.number as varchar(10))+','+a.type +','+ cast(a.status as varchar(9))+','+cast(b.number as varchar(10))+','+b.type +','+ cast(b.status as varchar(9)) txt into a 
from master..spt_values a cross join master..spt_values b 

XML:

SELECT count(t.c.value('.', 'VARCHAR(20)')) 
FROM (
    SELECT top 100000 x = CAST('<t>' + 
      REPLACE(txt, ',', '</t><t>') + '</t>' AS XML) 
      from a 
) a 
CROSS APPLY x.nodes('/t') t(c) 

Elapsed time: 1:21 seconds 

f_split:

select count(*) from a cross apply clausens_base.dbo.f_split(a.txt, ',') 

Elapsed time: 43 seconds 

這將在每次運行改變,但你想法

+0

如果''@ param'''爲null,我認爲set'''@param + = @ delimiter'''應該設置爲'''@param = ISNULL(@param,'')+ @ delimiter''' –

+0

@SuryaPratap簡單而簡單 - 沒有。這對結果沒有任何影響。 –

3

嘗試這一個 -

DDL:

CREATE TABLE dbo.Table1 (
     [EmpId] INT 
    , [FirstName] VARCHAR(7) 
    , [LastName] VARCHAR(10) 
    , [domain] VARCHAR(6) 
    , [Vertical] VARCHAR(10) 
    , [Account] VARCHAR(50) 
    , [City] VARCHAR(50) 
) 

INSERT INTO dbo.Table1 ([EmpId], [FirstName], [LastName], [Vertical], [Account], [domain], [City]) 
VALUES 
    (345, 'Priya', 'Palanisamy', 'DotNet', 'LS', 'Abbott', 'Chennai'), 
    (346, 'Kavitha', 'Amirtharaj', 'DotNet', 'CG', 'Diageo', 'Chennai'), 
    (647, 'Kala', 'Haribabu', 'DotNet', 'DotNet', 'IMS', 'Chennai') 

查詢:

DECLARE @Account VARCHAR(200) 
SELECT @Account = 'CG,LS' 

SELECT * 
FROM Table1 
WHERE [Vertical] = 'DotNet' AND (ISNULL(@Account, '') = '' OR Account IN (
    SELECT t.c.value('.', 'VARCHAR(20)') 
    FROM (
     SELECT x = CAST('<t>' + 
       REPLACE(@Account, ',', '</t><t>') + '</t>' AS XML) 
    ) a 
    CROSS APPLY x.nodes('/t') t(c) 
)) 

輸出:

proff

擴展統計:

stat

SSMS SET STATISTICS TIME + IO:

XML:

(3720 row(s) affected) 
Table 'temp'. Scan count 3, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 187 ms, elapsed time = 242 ms. 

CTE:

(3720 row(s) affected) 
Table '#BF78F425'. Scan count 360, logical reads 360, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'temp'. Scan count 1, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 281 ms, elapsed time = 335 ms. 
+0

試試這樣做:WHERE [Vertical] = @Vertical AND(@Account IS NULL或Account IN(...))' – Devart

+0

Thank you for the Response我嘗試過但在這裏應該返回2條記錄0條只返回 – user2514925

+0

[EmpId],[FirstName],[LastName],[Domain],[Vertical],[Account] 345,'Priya','Palanisamy','DotNet' ,'LS','Abbott'346,'Kavitha','Amirtharaj','DotNet','CG','Diageo'647,'Kala','Haribabu','DotNet','DotNet'我想使用Storedprocedure(通過動態傳遞垂直,賬戶值)得到「select * from table where vertical ='DotNet'和Account in('CG','LS')」的查詢結果 – user2514925

2

T他最有效的方法是使用CLR函數進行拆分字符串。請參閱this article的示例和性能比較

+0

該文章中描述的CTE功能非常弱(與我描述的相比)。他在CTE中選擇了所有的值,而不是找到分隔符的位置。這是以更多的計算機資源爲代價,而不是真正給CTE一個公平的機會。 –