我编写了一个sql server函数,它在第N个字符出现之前返回子字符串。
例如,
$( function () { //wait for document to be ready
$(".anchorShow").on("click", function (evt) { //bind the click event to the anchors
evt.preventDefault(); //stop click
var anchor = $(this); //link that was clicked
var wrapper = anchor.closest(".MainOuterDiv"); //parent element that wraps content
wrapper.find(".IntroductionDiv").show(); //show intro
wrapper.find(".FeaturesDiv").hide(); //hide features
});
});
回报'hello world.It.Is。'结果。
我写的函数看起来很脏而且很慢,所以我想优化它。 任何建议让它清洁是值得赞赏的。
谢谢。
SELECT dbo.fn_getFirstNthSentence('.', 'hello world.It.is.raining.today', 3)
答案 0 :(得分:1)
- 我发现这些功能是一个雷区,并且冒着踩到矿井的风险,我尝试了一些简化 - 可能是性能的微观改进
alter FUNCTION fn_getFirstNthSentence
(
@TargetStr VARCHAR(MAX) ,
@SearchedStr VARCHAR(8000) ,
@Occurrence INT
)
RETURNS varchar(MAX)
AS
BEGIN
DECLARE @pos INT ,
@counter INT ;
IF @Occurrence < 1
RETURN NULL;
SELECT @counter = 0, @POS = 1;
WHILE (@counter < @Occurrence AND @POS > 0)
BEGIN
SELECT @POS = CHARINDEX(@TargetStr, @SearchedStr,
@pos + 1);
IF @POS > 0
SET @counter = @counter + 1;
END;
RETURN CASE WHEN @POS > 0 THEN
LEFT(@SearchedStr, @POS)
ELSE
@SearchedStr
END;
END;
答案 1 :(得分:1)
另一种选择是通过XML
我无法看到您的基准测试,但它的代码肯定要少得多。添加选项可以是通过添加参数并将 Where Seq&lt; = @ FindPos 更改为其中Seq介于range1和range2 之间来查找第3到第5次。
Declare @FindPos int = 3
Declare @String varchar(max) = 'hello world.It.is.raining.today'
Declare @Delim varchar(10) = '.'
Declare @XML xml,@RetVal varchar(max) = ''
Set @XML = Cast('<x>' + Replace(@String,@Delim,'</x><x>')+'</x>' as XML)
Declare @Table table (Seq int identity(1,1),String varchar(max))
Insert Into @Table Select ltrim(rtrim(String.value('.', 'varchar(max)')))+@Delim as value FROM @XML.nodes('x') as T(String)
Select @RetVal=@RetVal + String from @Table Where Seq<=@FindPos Order By Seq
Select @RetVal
返回
hello world.It.is.
编辑:如果有帮助,下面是我的通用解析函数,它返回一个 标准化表...
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimeter varchar(10))
--Usage: Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
-- Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
-- Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|')
-- Select * from [dbo].[udf-Str-Parse]('hello world. It. is. . raining.today','.')
Returns @ReturnTable Table (Key_PS int IDENTITY(1,1), Key_Value varchar(max))
As
Begin
Declare @XML xml;Set @XML = Cast('<x>' + Replace(@String,@Delimeter,'</x><x>')+'</x>' as XML)
Insert Into @ReturnTable Select Key_Value = ltrim(rtrim(String.value('.', 'varchar(max)'))) FROM @XML.nodes('x') as T(String)
Return
End
例如:
Select * from [dbo].[udf-Str-Parse]('hello world.It.is.raining.today','.')
返回
Key_PS Key_Value
1 hello world
2 It
3 is
4 raining
5 today
答案 2 :(得分:1)
这是使用分隔字符串拆分器的另一种选择。已发布的XML方法很好,但这种方法不需要表变量。
这是作为内联表值函数创建的,它应该能够非常快速地保持性能。
create function fn_getFirstNthSentence
(
@SearchedStr varchar(100)
, @Occurrence int
, @Delimiter char(1)
) returns table as return
with ParsedValues as
(
select Item
, ItemNumber
from dbo.DelimitedSplit8K(@SearchedStr, @Delimiter)
where ItemNumber <= @Occurrence
)
select top 1 ResultString = STUFF(
(
select @Delimiter + Item
from ParsedValues
order by ItemNumber
for xml path('')), 1,1, '') + @Delimiter
from ParsedValues
这也是使用Jeff Moden创建的分离器。它有一个功能,即其他分离器都没有...一列来指示值来自哪个位置。你可以在这里找到他的文章。 http://www.sqlservercentral.com/articles/Tally+Table/72993/
然后,如果你想执行它,你可以很简单地做到这一点。
declare @String varchar(100) = 'hello world.It.is.raining.today.'
, @Num int = 3
, @Delimiter char(1) = '.'
;
select *
from fn_getFirstNthSentence(@String, @Num, @Delimiter)
如果你不喜欢Jeff Moden的分配器,你可以在这里找到其他几种选择。 http://sqlperformance.com/2012/07/t-sql-queries/split-strings我不会使用Moden的所有内容,但是当你需要保持解析后的值时,它就会很棒。
- 编辑 -
以下是如何将其修改为标量函数而不是内联表值函数的方法。我倾向于保持itvf,因为它们更快,更灵活。
create function fn_getFirstNthSentenceScalar
(
@SearchedStr varchar(100) = 'hello world.It.is.raining.today.this is after 5'
, @Occurrence int = 5
, @Delimiter char(1) = '.'
) returns varchar(max) as begin
declare @RetVal varchar(max);
with ParsedValues as
(
select Item
, ItemNumber
from dbo.DelimitedSplit8K(@SearchedStr, @Delimiter)
where ItemNumber <= @Occurrence
)
select top 1 @RetVal = STUFF(
(
select @Delimiter + Item
from ParsedValues
order by ItemNumber
for xml path('')), 1,1, '') + @Delimiter
from ParsedValues;
return @RetVal
end