在SQL中获取首个两个特定字符之间的字符

3

我在 SQL 中有数据(仅作说明:SQL StudioIDE),数据如下:

data
a_10_b_c
a_1_b_c

我想获取第一个和第二个符号_之间的数据:

Output
10
1

1
你现在有什么查询? - Anthony N.
从 [SecCharDB].[dbo].[locationmapping] 中选取子字符串(LocationID,charindex('', LocationID)+1,LEN(LocationID) - CHARINDEX('', LocationID) - CHARINDEX('_', REVERSE(LocationID))),类似于这样但是此代码无法执行。 - Vasista B
1
这是用于哪种关系型数据库管理系统?请添加一个标签以指定您是否使用 mysqlpostgresqlsql-serveroracledb2 - 或者完全使用其他内容。 - marc_s
1
它是针对SQL Server的,IDE是SSMS。 - Vasista B
尝试截取(LocationID,charindex('-', LocationID),charindex('-', LocationID,charindex('-', LocationID)+1)-charindex('-', LocationID))的子字符串。 - Anthony N.
显示剩余3条评论
2个回答

4
这是我的方法:

这将是我的做法:

SELECT CAST('<x>' + REPLACE(data,'_','</x><x>') + '</x>' AS XML).value('/x[2]','int')
FROM YourTable

首先将其转换为XML,然后选择第二个节点。

编辑:以下是更多适用此方法的示例:

CROSS APPLY:您可以使用此方法一次获取多个令牌

DECLARE @tbl TABLE(separated VARCHAR(100));
INSERT INTO @tbl VALUES('1_23:50_Look_this_is_a_test'),('2_12:00_that''s_one_more_test'),('3_13:30_great!_It_works!');

SELECT Converted.value('/x[1]','int') AS number
      ,Converted.value('/x[2]','time') AS time
      ,Converted.value('/x[3]','varchar(max)') AS text
FROM @tbl
CROSS APPLY(SELECT CAST('<x>' + REPLACE(separated,'_','</x><x>') + '</x>' AS XML) AS Converted) AS MySeparated
--type-safe and easy:
/*
number  time    text
1       23:50   Look
2       12:00   that's
3       13:30   great!
*/
GO

CTE:作为参数使用

DECLARE @Parameter VARCHAR(100)='1_12:30_SomeValue';
WITH MyParameters AS
(
    SELECT CAST('<x>' + REPLACE(@Parameter,'_','</x><x>') + '</x>' AS XML).value('/x[1]','int') AS IntParam
          ,CAST('<x>' + REPLACE(@Parameter,'_','</x><x>') + '</x>' AS XML).value('/x[2]','time') AS TimeParam
          ,CAST('<x>' + REPLACE(@Parameter,'_','</x><x>') + '</x>' AS XML).value('/x[3]','varchar(max)') AS TextParam
)
SELECT IntParam,TimeParam,TextParam
FROM MyParameters
/*
IntParam    TimeParam   TextParam
1           12:30:00    SomeValue
*/
GO

分割字符串:转换为列表

DECLARE @MyIDs VARCHAR(100)='3,5,7';
SELECT A.B.value('.','int') TheIntValue
FROM(SELECT CAST('<x>' + REPLACE(@MyIDs,',','</x><x>') + '</x>' AS XML) AS MyListAsXML) AS x
CROSS APPLY MyListAsXML.nodes('/x') AS A(B)

/*
TheIntValue
3
5
7
*/
GO

动态IN语句

DECLARE @tbl TABLE(ID INT,Content VARCHAR(max));
INSERT INTO @tbl VALUES(1,'Value 1'),(2,'Value 2'),(3,'Value 3'),(4,'Value 4'),(5,'Value 5'),(6,'Value 6'),(7,'Value 7');

DECLARE @MyIDs VARCHAR(100)='3,5,7';
/*
This won't work (due to the fact, that @MyIDs is not a list of INTs but a text
SELECT * FROM @tbl WHERE ID IN(@MyIDs)
*/
WITH AsList AS
(
    SELECT A.B.value('.','int') TheIntValue
    FROM(SELECT CAST('<x>' + REPLACE(@MyIDs,',','</x><x>') + '</x>' AS XML) AS MyListAsXML) AS x
    CROSS APPLY MyListAsXML.nodes('/x') AS A(B)

)
SELECT * FROM @tbl WHERE ID IN(SELECT TheIntValue FROM AsList)

/*
ID  Content
3   Value 3
5   Value 5
7   Value 7
*/

@VasistaKrishnaBaderdinni,我喜欢这种方法有两个原因:第一,你可以立即选择所有需要的节点。第二,你可以获得类型安全的值... - Shnugo
同时它也解决了我的问题,因为我不想先加入再查找或拆分,我希望在进行数据收集时就能够实现。 - Vasista B
@VasistaKrishnaBaderdinni,我编辑了我的回答。这种方法在许多情况下都非常有用。请随意分享... - Shnugo

2

您可以使用嵌套字符串函数来完成此操作。通常,使用outer apply更简单:

select t3.output
from t outer apply
     (select stuff(t.col, 1, charindex('_', t.col), '') as col2
     ) t2 outer apply
     (select left(t2.col2, charindex('_', t2.col2)) as output
     ) t3;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接