【问题标题】:T-SQL SUBSTRING with CHARINDEX as Length parameter使用 CHARINDEX 作为长度参数的 T-SQL SUBSTRING
【发布时间】:2018-12-12 14:05:42
【问题描述】:

我有下面的 sql。 where 后面的 AND 语句应该确保名称中确实有第二个空格,例如在中间名/首字母之后。此列中的名称为倒序,Last、First、Middle。我正在尝试获取名字,如果存在的话,它将是第二个位置的名字。我得到了无效的长度参数,不知道为什么,我认为我的 AND 语句会处理它。

样本数据:

Consultant_Contacted
Sample Name Test
Sample Name S
Name S Sample2

预期结果:

Consultant_Last_Name | Consultant_First_Name
Sample               | Name
Name                 | Sample2

我正在通过查找 A.Ordering_pty_name = '' 来处理倒序的名称

WHEN A.Ordering_pty_name = ''
AND (CHARINDEX(' ', A.Consultant_Contacted, CHARINDEX(' ', A.Consultant_Contacted) + 1) + 1) > 0
    THEN UPPER(
        RTRIM(
            LTRIM(
                SUBSTRING(
                    A.Consultant_Contacted
                    , CHARINDEX(' ', A.Consultant_Contacted, 1) 
                    --, 100
                    , (
                        CHARINDEX(
                            ' '
                            , A.CONSULTANT_CONTACTED
                            , CHARINDEX(
                                ' '
                                , A.CONSULTANT_CONTACTED
                                ) + 1
                            ) + 1 
                        ) - 
                        (
                        CHARINDEX(
                            ' '
                            , A.CONSULTANT_CONTACTED
                            , 1
                            )
                        )
                    )
                )
            )
        )

【问题讨论】:

  • 一些示例数据在这里真的很有帮助。
  • 还有预期的结果也别忘了。

标签: sql-server tsql split sql-server-2014


【解决方案1】:

解析名称可能是一个滑坡。

您可以使用 parsename(),但 XML 方法对我来说似乎更直观一些。

示例

Declare @YourTable table (Consultant_Contacted varchar(100))
Insert Into @YourTable values
('Sample Name Test'),
('Sample Name S'),
('Name S Sample2')

Select Distinct
       Last_Name  = Pos1
      ,First_Name = case when len(Pos2)=1 then Pos3 else Pos2 end
 From  @YourTable A
 Cross Apply (
                 Select Pos1 = n.value('/x[1]','varchar(100)')
                       ,Pos2 = n.value('/x[2]','varchar(100)')
                       ,Pos3 = n.value('/x[3]','varchar(100)')
                  From  (Select cast('<x>' + replace(A.Consultant_Contacted,' ','</x><x>')+'</x>' as xml) as n) X
             ) B

退货

Last_Name   First_Name
Name        Sample2
Sample      Name

【讨论】:

  • 这就是为什么我喜欢 SO,我一直在学习新东西。谢谢约翰,我会试一试
  • @MCP_infiltrator 我的观点完全正确!
  • 我需要探索这个as xml 我已经用过两次了,效果很好。我会接受比我的解析混乱更优雅的解决方案。
  • @MCP_infiltrator 我是一个缓慢的 XML 采用者。值得您花时间多玩一下。
【解决方案2】:

你也可以得到想要的结果

CREATE TABLE T(Col varchar(100))

INSERT INTO T VALUES
('Sample Name Test'),
('Sample Name S'),
('Name S Sample2');

WITH C AS(
SELECT Col,
       LEFT(Col, CHARINDEX(' ', Col, 1)-1) As Part1,
       RIGHT(Col, CHARINDEX(' ', REVERSE(Col), 1)-1 ) As Part3
FROM T
),
CC AS
(
  SELECT C.Part1,
     REPLACE(SUBSTRING(C.Col, LEN(C.Part1)+2,  LEN(C.Col)) , C.Part3, '') As Part2, 
     C.Part3
  FROM C
)

SELECT DISTINCT
       Part1 Consultant_Last_Name,
       CASE WHEN LEN(Part2) < LEN(Part3) THEN Part3
            ELSE Part2
       END Consultant_First_Name
FROM CC;

【讨论】:

    猜你喜欢
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 2023-03-10
    • 2013-05-29
    • 2021-03-26
    • 2017-07-28
    相关资源
    最近更新 更多