我有两个场景。第一个是快速的,但不是一个选择。第二个使用函数并杀死索引。这些值看起来类似于这个' ww,tt,tt,bb'。他们可以根据需要添加尽可能多的代码。有没有比使用该功能更好的方法?这是使用server 2008的存储过程。
没有功能:
WHERE date BETWEEN '20140701' AND '20140731' and
LEFT(id, 2) IN ('wp')
使用功能:
WHERE date BETWEEN '20140701' AND '20140731' and
LEFT(id, 2) IN (SELECT* FROM Toolbox.dbo.Split_DelimitedString_fn(@string,',') )
答案 0 :(得分:0)
我的建议是先将字符串拆分并将结果插入临时表:
INSERT INTO #tmp
SELECT *
FROM Toolbox.dbo.Split_DelimitedString_fn(@string,',')
然后将您的查询重写为
WHERE date BETWEEN '20140701' AND '20140731' and
LEFT(id, 2) IN (SELECT * FROM #tmp)
答案 1 :(得分:0)
因此,如果我正确理解了这个问题,你想让'in'子句由另一个表中的内容动态确定。
你试过了吗?
WHERE date BETWEEN '20140701' AND '20140731' and
LEFT(id, 2) IN (SELECT <column> FROM Toolbox.dbo.tblname)
第二次尝试: 将Left(id,2)移动到select子句中,然后对那些列进行过滤
select
<current query>
,Left(id,2) as sort
from
<current query>
WHERE date BETWEEN '20140701' AND '20140731' and
sort IN (SELECT* FROM Toolbox.dbo.Split_DelimitedString_fn(@string,',') )
答案 2 :(得分:0)
声明一个表变量,并插入值:
DECLARE @SplitIds TABLE
(
SplitId varchar(10)
)
Insert into @SplitIds (SplitIds)
SELECT field FROM Toolbox.dbo.Split_DelimitedString_fn(@string,',')
然后你可以加入这张桌子......
SELECT columns
FROM TableName a INNER JOIN @SplitIds b ON LEFT(id, 2) = b.SplitId
WHERE a.date BETWEEN '20140701' AND '20140731'
不确定这是否会加快查询速度,但您可以使用执行计划来帮助并检查索引。
答案 3 :(得分:0)
如果我理解正确,性能问题的核心是如何在SQL中有效地拆分CSV字符串。如果是这样my answer here如何使用Jeff Moden's Tally-Ho CSV Splitter可能是票。为清楚起见,在此重复:
功能定义:
CREATE FUNCTION [dbo].[DelimitedSplit8K]
--===== Define I/O parameters
(@pString VARCHAR(8000), @pDelimiter CHAR(1))
--WARNING!!! DO NOT USE MAX DATA-TYPES HERE! IT WILL KILL PERFORMANCE!
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
--===== "Inline" CTE Driven "Tally Table" produces values from 1 up to 10,000...
-- enough to cover VARCHAR(8000)
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
), --10E+1 or 10 rows
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows for
-- both performance gain and prevention of accidental "overruns"
SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER()
OVER (ORDER BY (SELECT NULL)) FROM E4
),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just
-- once for each delimiter)
SELECT 1 UNION ALL
SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
),
cteLen(N1,L1) AS(--==== Return start and length (for use in substring)
SELECT s.N1,
ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
FROM cteStart s
)
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final
-- element when no delimiter is found.
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l
;
go
上一个答案的用法示例;
with data as (
select Code,Location,Quantity,Store from ( values
('L698-W-EA', NULL, 2, 'A')
,('L82009-EA', 'A1K2, A1N2, C4Y3, CBP2', 2, 'A')
,('L80401-A-EA', 'A1S2, SHIP, R2F1, CBP5, BRP, BRP1-20', 17,'A')
,('CWD2132W-BOX-25PK', 'A-AISLE', 1, 'M')
,('GM22660003-EA', 'B1K2', 1, 'M')
)data(Code,Location,Quantity,Store)
)
,shredded as (
select Code,Location,Quantity,Store,t.*
from data
cross apply [dbo].[DelimitedSplit8K](data.Location,',') as t
)
select
pvt.Code,pvt.Quantity,pvt.Store
,cast(isnull(pvt.[1],' ') as varchar(8)) as Loc1
,cast(isnull(pvt.[2],' ') as varchar(8)) as Loc2
,cast(isnull(pvt.[3],' ') as varchar(8)) as Loc3
,cast(isnull(pvt.[4],' ') as varchar(8)) as Loc4
,cast(isnull(pvt.[5],' ') as varchar(8)) as Loc5
,cast(isnull(pvt.[6],' ') as varchar(8)) as Loc6
from shredded
pivot (max(Item) for ItemNumber in ([1],[2],[3],[4],[5],[6])) pvt;
;
go
得到以下特性:
Code Quantity Store Loc1 Loc2 Loc3 Loc4 Loc5 Loc6
----------------- ----------- ----- -------- -------- -------- -------- -------- --------
L698-W-EA 2 A
L82009-EA 2 A A1K2 A1N2 C4Y3 CBP2
L80401-A-EA 17 A A1S2 SHIP R2F1 CBP5 BRP BRP1-20
CWD2132W-BOX-25PK 1 M A-AISLE
GM22660003-EA 1 M B1K2