Sql server SQL查询-递归求精

Sql server SQL查询-递归求精,sql-server,tsql,common-table-expression,Sql Server,Tsql,Common Table Expression,我试图将一串由空格分隔的单词传递到存储过程中,我想做的是对这些单词执行SELECT,这样每个后续SELECT都会查询前面的结果集。我一直在研究如何使用递归CTE实现这一点,但我无法找到一种正确的方法来设置锚和终止符,以使递归正常工作。我知道我可以在服务器端代码(C#)上实现这一点,但我不想为了我知道可以在那里实现的事情而重复调用DB。下面是存储的过程,减去拆分字符串的任何拆分操作类型和我所做的任何黑客递归尝试(即,它所做的只是返回一个关键字的结果集): 听起来像是使用全文索引的理想方案,这样您就

我试图将一串由空格分隔的单词传递到存储过程中,我想做的是对这些单词执行SELECT,这样每个后续SELECT都会查询前面的结果集。我一直在研究如何使用递归CTE实现这一点,但我无法找到一种正确的方法来设置锚和终止符,以使递归正常工作。我知道我可以在服务器端代码(C#)上实现这一点,但我不想为了我知道可以在那里实现的事情而重复调用DB。下面是存储的过程,减去拆分字符串的任何拆分操作类型和我所做的任何黑客递归尝试(即,它所做的只是返回一个关键字的结果集):


听起来像是使用全文索引的理想方案,这样您就可以使用CONTAINS()

如果您没有访问全文索引的权限,可以尝试将字符串拆分为一个表,然后加入该表,然后计数重复项(通过对主键进行分区)。未测试的示例:

CREATE FUNCTION [dbo].[fnc_Split]
    (
      @Data VARCHAR(2000) ,
      @Sep VARCHAR(5)
    )
RETURNS @Temp TABLE
    (
      Id INT IDENTITY(1, 1) ,
      Data NVARCHAR(100)
    )
AS 
    BEGIN
        DECLARE @Cnt INT
        SET @Cnt = 1
        WHILE ( CHARINDEX(@Sep, @Data) > 0 ) 
            BEGIN
                INSERT  INTO @Temp
                        ( data
                        )
                        SELECT  Data = LTRIM(RTRIM(SUBSTRING(@Data, 1, CHARINDEX(@Sep, @Data) - 1)))
                SET @Data = SUBSTRING(@Data, CHARINDEX(@Sep, @Data) + 1, LEN(@Data))
                SET @Cnt = @Cnt + 1
            END
        INSERT  INTO @Temp
                ( data )
                SELECT  Data = LTRIM(RTRIM(@Data))
        RETURN
    END

GO

DECLARE @SearchString VARCHAR(MAX)
SET @SearchString = 'blood HIV white'

--#### Build Pattern Table
DECLARE @PatternTable TABLE
    (
      ID INT NOT NULL ,
      PATTERN VARCHAR(50)
    )
INSERT  INTO @PatternTable
        ( ID ,
          PATTERN
        )
        SELECT  ID ,
                CASE WHEN ID = 1 THEN Data + '%'
                     ELSE '% ' + Data + '%'
                END AS Data
        FROM    fnc_Split(@SearchString, ' ');

--#### Fetch list of matching Primary keys (repeat CTEs for each column)
WITH    PrepSearch ( PrimaryKey, MatchedWords )
          AS ( SELECT   PrimaryKey ,
                        COUNT(PrimaryKey) OVER ( PARTITION BY PrimaryKey ) AS MatchedWords
               FROM     dbo.RolodexTestDB P ( NOLOCK )
                        INNER JOIN @PatternTable S ON P.Methodology LIKE S.PATTERN COLLATE DATABASE_DEFAULT
             ),
        SearchResults ( PRO_CODE )
          AS ( SELECT   PrimaryKey
               FROM     PrepSearch
               WHERE    MatchedWords = (SELECT COUNT(ID) FROM @PatternTable)
               GROUP BY PrimaryKey
             )
    SELECT  *
    FROM    SearchResults

“每个后续SELECT查询之前的结果集”是什么意思。在非TSQL术语中,您试图实现什么?您能提供@searchQuery的样本值、RolodexTestDB中的一些样本数据和所需结果吗?否则很难准确解释您试图执行的操作。抱歉-我的解释不正确。@searchQuery的样本值可能是:“血色HIV-white”-我需要的是执行上述查询3次(或其他解决方案,完成相同的事情)-每次运行查询时,结果集都会被过滤(因此,第一次运行时,我会得到任何包含第一个项的记录;然后,我会使用第二个项对该结果集再次运行查询,依此类推).希望有意义。不,至少对我来说没有意义。过滤意味着所有术语都必须存在?
CREATE FUNCTION [dbo].[fnc_Split]
    (
      @Data VARCHAR(2000) ,
      @Sep VARCHAR(5)
    )
RETURNS @Temp TABLE
    (
      Id INT IDENTITY(1, 1) ,
      Data NVARCHAR(100)
    )
AS 
    BEGIN
        DECLARE @Cnt INT
        SET @Cnt = 1
        WHILE ( CHARINDEX(@Sep, @Data) > 0 ) 
            BEGIN
                INSERT  INTO @Temp
                        ( data
                        )
                        SELECT  Data = LTRIM(RTRIM(SUBSTRING(@Data, 1, CHARINDEX(@Sep, @Data) - 1)))
                SET @Data = SUBSTRING(@Data, CHARINDEX(@Sep, @Data) + 1, LEN(@Data))
                SET @Cnt = @Cnt + 1
            END
        INSERT  INTO @Temp
                ( data )
                SELECT  Data = LTRIM(RTRIM(@Data))
        RETURN
    END

GO

DECLARE @SearchString VARCHAR(MAX)
SET @SearchString = 'blood HIV white'

--#### Build Pattern Table
DECLARE @PatternTable TABLE
    (
      ID INT NOT NULL ,
      PATTERN VARCHAR(50)
    )
INSERT  INTO @PatternTable
        ( ID ,
          PATTERN
        )
        SELECT  ID ,
                CASE WHEN ID = 1 THEN Data + '%'
                     ELSE '% ' + Data + '%'
                END AS Data
        FROM    fnc_Split(@SearchString, ' ');

--#### Fetch list of matching Primary keys (repeat CTEs for each column)
WITH    PrepSearch ( PrimaryKey, MatchedWords )
          AS ( SELECT   PrimaryKey ,
                        COUNT(PrimaryKey) OVER ( PARTITION BY PrimaryKey ) AS MatchedWords
               FROM     dbo.RolodexTestDB P ( NOLOCK )
                        INNER JOIN @PatternTable S ON P.Methodology LIKE S.PATTERN COLLATE DATABASE_DEFAULT
             ),
        SearchResults ( PRO_CODE )
          AS ( SELECT   PrimaryKey
               FROM     PrepSearch
               WHERE    MatchedWords = (SELECT COUNT(ID) FROM @PatternTable)
               GROUP BY PrimaryKey
             )
    SELECT  *
    FROM    SearchResults