在 SQL Server 中解析字符的最后一个索引之前的字符串

发布于 2024-09-19 18:11:46 字数 1041 浏览 8 评论 0原文

我从这个开始,但这是执行任务的最佳方式吗?

select  
    reverse(
        substring(reverse(some_field),
        charindex('-', reverse(some_field)) + 1, 
        len(some_field) - charindex('-', reverse(some_field)))) 
from SomeTable
  1. SQL Server 如何处理 多次调用 反向(some_field)
  2. 除了 UDF 和迭代之外 寻找 charindex 的字符串 '-' 并存储最后一个 索引,还有吗 在 T-SQL 中执行此任务的有效方法是什么?

请注意,我所拥有的有效,我只是想知道这是否是最好的方法。

以下是 some_field 的一些示例值。

s2-st, s1-st, s3-st, s3-sss-zzz, s4-sss-zzzz

编辑:

此示例输出将是...

s1, s2, s3-sss, s3, s4-sss

ErikE 编写的解决方案实际上是获取字符串的结尾,因此最后一个连字符之后的所有内容。我只是修改了他的版本以获取之前的所有内容,而不是使用带有 left 函数的类似方法。感谢您的帮助。

select left(some_field, abs(charindex('-', reverse(some_field)) - len(some_field)))
    from (select 's2-st' as some_field
        union select 's1-st'
        union select 's3-st'
        union select 's3-sss-zzz'
        union select 's4-sss-zzzz') as SomeTable

I started with this but is it the best way to perform the task?

select  
    reverse(
        substring(reverse(some_field),
        charindex('-', reverse(some_field)) + 1, 
        len(some_field) - charindex('-', reverse(some_field)))) 
from SomeTable
  1. How does SQL Server treat the
    multiple calls to
    reverse(some_field)?
  2. Besides a UDF and iterating through
    the string looking for charindex
    of the '-' and storing the last
    index of it, is there a more
    efficient way to perform this task in T-SQL?

Note that what I have works, I just am really wondering if it is the best way about it.

Below are some sample values for some_field.

s2-st, s1-st, s3-st, s3-sss-zzz, s4-sss-zzzz

EDIT:

Sample output for this would be...

s1, s2, s3-sss, s3, s4-sss

The solution ErikE wrote is actually getting the end of the string so everything after the last hyphen. I just modified his version to get everything before it instead using a similar method with the left function. Thanks for all of your your help.

select left(some_field, abs(charindex('-', reverse(some_field)) - len(some_field)))
    from (select 's2-st' as some_field
        union select 's1-st'
        union select 's3-st'
        union select 's3-sss-zzz'
        union select 's4-sss-zzzz') as SomeTable

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

日裸衫吸 2024-09-26 18:11:46

我可以建议您简化表达式吗:

select right(some_field, charindex('-', reverse(some_field)) - 1)
from SomeTable

此外,据我所知,当您需要字符串的其余部分时,使用 substring 函数指定 8000 个字符的长度并没有什么坏处。只要它不是 varchar(max),它就可以正常工作。

如果这是您必须一直重复执行的操作,那么#1 将数据拆分为单独的列并以这种方式存储,或者 #2 添加带有索引的计算列,这将执行在更新/插入时计算一次,以后不再计算。

最后,我不知道SQL Server是否足够聪明,可以仅反转(some_field)一次并将其注入到另一个实例中。当我有时间时,我会尝试弄清楚。

更新

哎呀,不知怎的,我得到了你想要的东西。对此感到抱歉。您显示的新表达式仍然可以稍微简化:

select left(some_field, len(some_field) - charindex('-', reverse(some_field)))
from (
   select 's2-st'
   union all select 's1-st'
   union all select 's3-st'
   union all select 's3-sss-zzz'
   union all select 's4-sss-zzzz'
   union all select 's5'
) X (some_field)

表达式中的 abs() 只是反转符号。所以我用 + len - charindex 而不是 + charindex - len 现在一切都很好。它甚至适用于没有破折号的字符串。

还要提一下:您的 UNION SELECT 应该是 UNION ALL SELECT 因为如果没有 ALL,引擎必须删除重复项,就像您已指定SELECT DISTINCT。只需养成使用 ALL 的习惯,您的情况就会好得多。 :)

May I suggest this simplification of your expression:

select right(some_field, charindex('-', reverse(some_field)) - 1)
from SomeTable

Also, there's no harm, as far as I know, in specifying 8000 characters in length with the substring function when you want the rest of the string. As long as it's not varchar(max), it works just fine.

If this is something you have to do all the time, over and over, how about #1 splitting out the data into separate columns and storing it that way, or #2 adding a calculated column with an index on it, which will perform the calculation once at update/insert time and not again later.

Last, I don't know if SQL Server is smart enough to reverse(some_field) only once and inject it into the other instance. When I get some time I'll try to figure it out.

Update

Oops, somehow I got backwards what you wanted. Sorry about that. The new expression you showed can still be simplified a little:

select left(some_field, len(some_field) - charindex('-', reverse(some_field)))
from (
   select 's2-st'
   union all select 's1-st'
   union all select 's3-st'
   union all select 's3-sss-zzz'
   union all select 's4-sss-zzzz'
   union all select 's5'
) X (some_field)

The abs() in your expression was just reversing the sign. So I put + len - charindex instead of + charindex - len and all is well now. It even works for strings without dashes.

One more thing to mention: your UNION SELECTs should be UNION ALL SELECT because without the ALL, the engine has to remove duplicates just as if you'd indicated SELECT DISTINCT. Simply get in the habit of using ALL and you'll be much better off. :)

流心雨 2024-09-26 18:11:46

不确定#1,但我想说你最好在代码中这样做。有什么理由必须在数据库中执行此操作吗?

您是否因为某些类似的代码而遇到性能问题,或者这纯粹是假设的。

Not sure about #1, but I would say that you might be better off doing this in code. Is there a reason you have to do it in the database?

Are you experiencing performance problems because of some similar code or is this purely hypothetical.

情话墙 2024-09-26 18:11:46

我也不确定 SQL Server 如何处理对 REVERSE 和 CHARINDEX 的多次调用。

您可以消除对 CHARINDEX 的最后一次调用,因为您希望将所有内容都带到字符串的末尾:

select  
    reverse(
        substring(reverse(some_field),
        charindex('-', reverse(some_field)) + 1, 
        len(some_field))) 
from SomeTable

尽管我建议不要这样做,但您也可以用列的大小替换 LEN 函数调用:

select  
    reverse(
        substring(reverse(some_field),
        charindex('-', reverse(some_field)) + 1, 
        1024)) 
from SomeTable

我很好奇有多少这些改变中的任何一个都会产生差异。

I am also not sure how SQL Server handles the multiple calls to REVERSE and CHARINDEX.

You can eliminate the last call to CHARINDEX since you want to take everything to the end of the string:

select  
    reverse(
        substring(reverse(some_field),
        charindex('-', reverse(some_field)) + 1, 
        len(some_field))) 
from SomeTable

Although I would recommend against it, you could also replace the LEN function call with the size of the column:

select  
    reverse(
        substring(reverse(some_field),
        charindex('-', reverse(some_field)) + 1, 
        1024)) 
from SomeTable

I am curious how much of a difference either of these changes would make.

白况 2024-09-26 18:11:46
  1. 3 个内部反转彼此独立。外部反转将反转任何已被内部反转反转的内容。

  2. ErikE 的方法最适合作为纯 TSQL 解决方案。您不需要 LEN

  1. The 3 inner reverses are discrete from each other. The outer reverse will reverse anything that is already reversed by the inner ones.

  2. ErikE's approach is best as a pure TSQL solution. You don't need LEN

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文