【问题标题】:Get Last Word from String in Table从表中的字符串中获取最后一个单词
【发布时间】:2020-02-14 17:11:18
【问题描述】:

我正在尝试从 SQL-Server 2017 中的表 Project 中获取最后一句话。

我的代码如下:

select 
reverse(substring(reverse(ProjectDescription),1, charindex(' ', reverse(ProjectDescription)) -1)) as LastWord
from Project 

如果我要求将表格隔离为一行,则代码有效,但我需要字段 ProjectDescription 中所有行的最后一个字。

当我运行上述代码时,我收到以下错误:

传递给 LEFT 或 SUBSTRING 函数的长度参数无效。

请有人帮助我解决我哪里出错了。

【问题讨论】:

  • 您可能需要在提取子字符串之前检查字符串的长度 - 例如,它可能没有空格,因此charindex 的第二个参数可能为零。使用case/when 函数检查是否存在空间。
  • 谢谢彼得!只是一行有一个单词导致了问题。案例 排序时。

标签: sql-server


【解决方案1】:

迟到的答案,仅作为指导发布。

不需要拆分字符串。您的错误仅仅是因为 charindex() 返回零。简单的解决方法是在 charindex() 中添加一个“fail-safe”,方法是在字符串中添加一个空格,从而确保命中。

另外,请注意肖恩的建议。几年前我有一个类似的拆分函数,并且对性能提升感到惊讶。

示例

Declare @YourTable Table ([ID] varchar(50),[ProjectDescription] varchar(50))  Insert Into @YourTable Values 
 (1,'Some Project Item or Description') -- Multiword strubg
,(2,'OneWord    ')                      -- One word with trailing blanks
,(3,NULL)                               -- A NULL value
,(4,'')                                 -- An Empty String

Select * 
      ,LastWord = right(rtrim([ProjectDescription]),charindex(' ',reverse(rtrim([ProjectDescription]))+' ')-1)
 From  @YourTable 

退货

ID  ProjectDescription                  LastWord
1   Some Project Item or Description    Description
2   OneWord                             OneWord
3   NULL                                NULL
4       

【讨论】:

  • 我不是有意更改 ACCEPT
【解决方案2】:

我使用表值函数的组合将列表拆分为有序列表。然后使用 rownumber 只取最后一个。

这是一个函数。有很多这样的。

create FUNCTION SplitString
(    
      @Input NVARCHAR(MAX),
      @Character CHAR(1)
)
RETURNS @Output TABLE (
       ct int
      ,Item NVARCHAR(1000)
)
AS
BEGIN
      DECLARE @StartIndex INT, @EndIndex INT,@ct int =0

      SET @StartIndex = 1
      IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
      BEGIN
            SET @Input = @Input + @Character
      END

      WHILE CHARINDEX(@Character, @Input) > 0
      BEGIN
            SET @EndIndex = CHARINDEX(@Character, @Input)
            set @ct=@ct+1

            INSERT INTO @Output(Ct,Item)
            SELECT @ct,SUBSTRING(@Input, @StartIndex, @EndIndex - 1)

            SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
      END

      RETURN
END
GO

这是设置好的,所以我有一张桌子可以使用。你可以把它分给你的桌子。

declare @t as table(sentence varchar(max))

insert into @t
values
('The brown dog jumped over the fence')
,('This is the final word')

这是提取最后一个单词的 SQL:

select *
from (
        select * ,rn = ROW_NUMBER() over (partition by sentence order by ct desc)
        from @t t
            cross apply dbo.splitstring(t.sentence,' ')
    ) a
where rn=1

结果:

sentence                            ct  Item    rn
The brown dog jumped over the fence 7   fence   1
This is the final word              5   word    1

【讨论】:

  • 这个功能非常低效。多语句表值函数甚至比标量函数慢。有比使用循环更好的分割字符串的方法。 This onethese 中的任何一个,甚至是内置的 STRING_SPLIT
  • 我同意我买了一个基本的。该功能并不是问题的一部分。我的首选是 xml,因为我仍在 SQL 2012 中
  • @KeithL 这里是一个用于旧版本的软件,速度也很快。 sqlservercentral.com/articles/…
  • 是的,我知道这不是问题的一部分,但它是您解决方案不可或缺的一部分。我看不到那种拆分器被张贴而不说什么。 :)
【解决方案3】:

你可以使用这个简单的功能:

create function dbo.getLastWord(@s varchar(100))
returns varchar(200)
as
begin
declare @i int
set @i=len(@s)
 while substring(@s,@i,1)<>' '
  set @i=@i-1
 return substring(@s,@i,len(@s)-@i+1)
end

并称它为:

select dbo.getLastWord('Feels things getting better')

得到:

better

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 2015-01-01
    • 2022-12-18
    相关资源
    最近更新 更多