【问题标题】:Get the character between first 2 special character in SQL获取SQL中前2个特殊字符之间的字符
【发布时间】:2016-02-12 23:22:46
【问题描述】:

我在sql 中有数据(请注意:SQL STudioIDE),例如:

data
a_10_b_c
a_1_b_c

我想获取前两个符号_之间的数据:

Output
10
1

【问题讨论】:

  • 你现在有什么查询?
  • 选择子串(LocationID,charindex('', LocationID)+1,LEN(LocationID) - CHARINDEX('', LocationID) - CHARINDEX('_', REVERSE (LocationID))) FROM [SecCharDB].[dbo].[locationmapping] - 类似这样的东西,但这不起作用
  • 这适用于哪个 RDBMS?请添加标签以指定您使用的是mysqlpostgresqlsql-serveroracle 还是db2 - 或其他完全不同的东西。
  • 用于SQL server,IDE为SSMS
  • try substring(LocationID,charindex('-', LocationID),charindex('-', LocationID,charindex('-', LocationID)+1)-charindex('-', LocationID) )

标签: sql sql-server substring


【解决方案1】:

您可以使用嵌套的字符串函数来做到这一点。通常,使用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;

【讨论】:

    【解决方案2】:

    这将是我的方法:

    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,我更喜欢这种方法,原因有两个:第一:您可以立即选择所有需要的节点。第二:你得到的值类型是安全的......
    • 它也解决了我的目的,因为我想加入然后查找或拆分,我希望它继续进行,因为我正在将信息收集到 Python 中进行数据分析
    • @VasistaKrishnaBaderdinni,我编辑了我的答案。该方法在许多情况下都非常有用。随意分享这个...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 2015-05-14
    • 2021-01-14
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多