【问题标题】:Return all words starting with a character in a column返回以列中的字符开头的所有单词
【发布时间】:2017-12-11 19:15:35
【问题描述】:

我有一个 VARCHAR 列,其中包含如下数据:

abc = :abc and this = :that

我需要一个查询来查找此数据列中所有以冒号开头的特殊“单词”。我真的不需要任何其他数据(ID 或其他数据),重复就可以了。如果需要,我可以稍后在 Excel 中删除重复项。所以如果这是唯一的一行,我想要这样的输出:

SpecialWords
:abc
:that

我认为它需要一个 CHARINDEX 或类似的东西。但由于列中可能有多个特殊词,我不能只找到第一个 : 并删除其余部分。

非常感谢任何帮助!提前致谢!

【问题讨论】:

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


    【解决方案1】:

    您必须根据空格 拆分此值并仅返回以冒号 : 开头的字段,我根据您需要的结果类型(表格或单值)提供了 2 个解决方案来实现此目的

    表值函数

    您可以创建一个 TV 函数来将此列拆分为一个表格:

    CREATE FUNCTION [dbo].[GETVALUES] 
        (   
        @DelimitedString    varchar(8000)
        )
    RETURNS @tblArray TABLE
        (
        ElementID   int IDENTITY(1,1),  -- Array index
        Element     varchar(1000)               -- Array element contents
        )
    AS
    BEGIN
    
        -- Local Variable Declarations
        -- ---------------------------
        DECLARE @Index      smallint,
                        @Start      smallint,
                        @DelSize    smallint
    
        SET @DelSize = 1
    
        -- Loop through source string and add elements to destination table array
        -- ----------------------------------------------------------------------
        WHILE LEN(@DelimitedString) > 0
        BEGIN
    
            SET @Index = CHARINDEX(' ', @DelimitedString)
    
            IF @Index = 0
                BEGIN
    
                IF ((LTRIM(RTRIM(@DelimitedString))) LIKE ':%')
                    INSERT INTO
                        @tblArray 
                        (Element)
                    VALUES
                        (LTRIM(RTRIM(@DelimitedString)))
    
                    BREAK
                END
            ELSE
                BEGIN
    
                 IF (LTRIM(RTRIM(SUBSTRING(@DelimitedString, 1,@Index - 1)))) LIKE ':%'
                    INSERT INTO
                        @tblArray 
                        (Element)
                    VALUES
                        (LTRIM(RTRIM(SUBSTRING(@DelimitedString, 1,@Index - 1))))
    
                    SET @Start = @Index + @DelSize
                    SET @DelimitedString = SUBSTRING(@DelimitedString, @Start , LEN(@DelimitedString) - @Start + 1)
    
                END
        END
    
        RETURN
    END
    

    你可以像下面这样使用它:

    DECLARE @SQLStr varchar(100)
    SELECT @SQLStr = 'abc = :abc and this = :that and xyz = :asd'
    
    SELECT
        *
    FROM
     dbo.GETVALUES(@SQLStr)
    

    结果:

    标量值函数

    如果您需要返回一个值(不是表格),那么您可以使用此函数返回由 分隔的所有值(换行符 + 回车符返回 CHAR(13) + CHAR(10)

    CREATE FUNCTION dbo.GetValues2
    (
        @DelimitedString    varchar(8000)
    )
    RETURNS varchar(8000)
    AS
    BEGIN
    
           DECLARE @Index      smallint,
                        @Start      smallint,
                        @DelSize    smallint,
                        @Result varchar(8000)
    
        SET @DelSize = 1
        SET @Result = ''
    
        WHILE LEN(@DelimitedString) > 0
        BEGIN
    
            SET @Index = CHARINDEX(' ', @DelimitedString)
    
            IF @Index = 0
                BEGIN
    
                if (LTRIM(RTRIM(@DelimitedString))) LIKE ':%'
               SET @Result = @Result + char(13) + char(10) +  (LTRIM(RTRIM(@DelimitedString)))
    
                    BREAK
                END
            ELSE
                BEGIN
    
                 IF (LTRIM(RTRIM(SUBSTRING(@DelimitedString, 1,@Index - 1)))) LIKE ':%'
    
                        SET @Result = @Result + char(13) + char(10) + (LTRIM(RTRIM(SUBSTRING(@DelimitedString, 1,@Index - 1))))
    
                    SET @Start = @Index + @DelSize
                    SET @DelimitedString = SUBSTRING(@DelimitedString, @Start , LEN(@DelimitedString) - @Start + 1)
    
                END
        END
    
    
        return @Result
    END
    GO
    

    你可以像下面这样使用它

    DECLARE @SQLStr varchar(100)
    SELECT @SQLStr = 'abc = :abc and this = :that and xyz = :asd'
    
    SELECT dbo.GetValues2(@SQLStr)
    

    结果

    表格结果换行不可见,只需将数据复制到编辑器,它就会出现如图所示

    参考文献

    【讨论】:

      【解决方案2】:

      一种方法是编写专门的 SPLIT 函数。我建议从 Internet 上获取 TSQL 拆分函数,看看是否可以根据需要调整代码。

      从头开始,您可以编写一个函数,使用 CHARINDEX 循环遍历列值,直到找不到更多 : 字符。

      【讨论】:

        【解决方案3】:

        使用charindex 怎么样?

        rextester 示例:

        create table mytable (testcolumn varchar(20))
        insert into mytable values ('this = :that'),('yes'), (':no'), ('abc = :abc')
        
        
        select right(testcolumn, charindex(':', reverse(testcolumn)) - 1) from mytable
        where testcolumn like '%:%'
        

        参考

        SQL Select everything after character

        更新

        解决萨米人的问题:

        没有看到两个单词可以在一个冒号中,怎么样?

        select replace(substring(testcolumn, charindex(':', testcolumn), len(testcolumn)), ':', '')
        

        再次更新

        我明白了,实际语句是this = :that and that = :this

        【讨论】:

        • this = :that :lose 呢?
        • 我尝试在 rextester 上运行你的,但如果你输入它“this = :that and that = :this”,它会失败,因为在同一列中有 2 个带有 : 的东西
        【解决方案4】:

        如果性能很重要,那么您想使用内联表值函数来拆分字符串并提取您需要的内容。您可以为此使用delimitedSplit8KdelimitedSplit8K_lead

        declare @string varchar(8000) = 'abc = :abc and this = :that';
        
        select item 
        from dbo.DelimitedSplit8K(@string, ' ')
        where item like ':%';
        

        返回:

        item
        ------
        :abc
        :that
        

        为了获得比我上面发布的更好的性能,您可以像这样使用ngrams8k

        declare @string varchar(8000) = 'abc = :abc and this = :that';
        
        select position, item = 
          substring(@string, position,
            isnull(nullif(charindex(' ',@string,position+1),0),8000)-position)
        from dbo.ngrams8k(@string, 1)
        where token = ':';
        

        这甚至可以为您提供正在搜索的项目的位置:

        position   item
        ---------- -------
        7          :abc
        23         :that
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-03-12
          • 2011-10-24
          • 1970-01-01
          • 2012-07-10
          • 1970-01-01
          • 2019-11-27
          相关资源
          最近更新 更多