在每个单词上使用单词“like”查询

时间:2017-11-16 08:16:46

标签: sql sql-server tsql azure-sql-database

我已经得到了这个查询,它可以正确地循环一组单词并在每个单词的某些字段上执行类似的条件,并在需要时搜索DOB。

任何人都可以在需要While循环的过程中看到这样做的方法吗?我无法找到使用STRING_SPLIT执行此操作的方法,但我无法使用此方法添加LIKE。

SET STATISTICS IO ON
SET STATISTICS TIME ON

--what will become stored proc parameters
DECLARE @searchwords NVARCHAR(max) = 'mary jo' --can accept many search words
DECLARE @LowerDate date = '01 Jan 1980' --could be NULL
DECLARE @UpperDate date = '31 Dec 1980' --could be NULL
--local variables
DECLARE @word NVARCHAR(50)
Declare @ID int

Create Table #SearchWords
(
    ID int IDENTITY(1,1),
    Word varchar(50)
)

Create Table #Results
(
    ClientID int,
    FirstName varchar(50),
    LastName varchar(50),
    VerificationCode varchar(100),
    DOB date
)

Insert into #SearchWords
(
    Word
)
SELECT 
    value 
FROM 
    STRING_SPLIT(@searchwords, ' ')  
WHERE 
    RTRIM(value) <> ''  

While (Select Count(*) From #SearchWords) > 0
Begin

    Select Top 1 
        @ID = ID,
        @Word = Word
    From 
        #SearchWords

    INSERT INTO #Results
    (
        ClientID,
        FirstName,
        LastName,
        VerificationCode,
        DOB
    )
    SELECT
        ClientID,
        FirstName,
        LastName,
        VerificationCode,
        DOB
    FROM
        Client
    WHERE
       (FirstName like '%' + @Word + '%' or
        LastName like '%' + @Word + '%' or
        VerificationCode like '%' + @Word + '%')

    Delete #SearchWords Where ID = @ID
End

IF (@LowerDate IS NOT NULL and @UpperDate IS NOT NULL)
BEGIN
    INSERT INTO #Results
    (
        ClientID,
        FirstName,
        LastName,
        VerificationCode,
        DOB
    )
    SELECT
        ClientID,
        FirstName,
        LastName,
        VerificationCode,
        DOB
    FROM
        Client
    WHERE
       (DOB >= @LowerDate and DOB <= @UpperDate)
END

select * from #Results

drop table #Results
drop table #SearchWords

1 个答案:

答案 0 :(得分:1)

尝试使用以下查询

SELECT
    ClientID,
    FirstName,
    LastName,
    VerificationCode,
    DOB
FROM Client c
WHERE EXISTS(
          SELECT *
          FROM #SearchWords s
          WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
             OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
             OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
        )
  AND DOB BETWEEN ISNULL(@LowerDate,DOB) AND ISNULL(@UpperDate,DOB)

评论中问题的变体

SELECT
    ClientID,
    FirstName,
    LastName,
    VerificationCode,
    DOB
INTO #Result
FROM Client c
WHERE EXISTS(
          SELECT *
          FROM #SearchWords s
          WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
             OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
             OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
        )
  AND DOB BETWEEN ISNULL(@LowerDate,DOB) AND ISNULL(@UpperDate,DOB)

IF(EXISTS(SELECT * FROM #Result))
BEGIN
  SELECT *
  FROM #Result
END
ELSE
BEGIN
  SELECT
      ClientID,
      FirstName,
      LastName,
      VerificationCode,
      DOB
  FROM Client
  WHERE DOB BETWEEN ISNULL(@LowerDate,DOB) AND ISNULL(@UpperDate,DOB)
END

DROP TABLE #Result

没有临时表的变体

SELECT TOP 1 WITH TIES
  ClientID,
  FirstName,
  LastName,
  VerificationCode,
  DOB
FROM
  (
    SELECT
        1 RowPriority,
        ClientID,
        FirstName,
        LastName,
        VerificationCode,
        DOB
    FROM Client c
    WHERE EXISTS(
              SELECT *
              FROM #SearchWords s
              WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
                 OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
                 OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
            )
      AND DOB BETWEEN ISNULL(@LowerDate,DOB) AND ISNULL(@UpperDate,DOB)

    UNION ALL

    SELECT
        2 RowPriority,
        ClientID,
        FirstName,
        LastName,
        VerificationCode,
        DOB
    FROM Client c
    WHERE DOB BETWEEN ISNULL(@LowerDate,DOB) AND ISNULL(@UpperDate,DOB)
  ) q
ORDER BY RowPriority

另一个变种

SELECT TOP 1 WITH TIES
  ClientID,
  FirstName,
  LastName,
  VerificationCode,
  DOB
FROM
  (
    -- the first scenario - we use only words filter without the DOB filter
    SELECT
        1 RowPriority, -- max priority
        ClientID,
        FirstName,
        LastName,
        VerificationCode,
        DOB
    FROM Client c
    WHERE EXISTS(
              SELECT *
              FROM #SearchWords s
              WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
                 OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
                 OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
            )
      AND @LowerDate IS NULL

    UNION ALL

    -- the second scenario - we use words and DOB filters
    SELECT
        2 RowPriority,
        ClientID,
        FirstName,
        LastName,
        VerificationCode,
        DOB
    FROM Client c
    WHERE EXISTS(
              SELECT *
              FROM #SearchWords s
              WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
                 OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
                 OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
            )
      AND DOB BETWEEN @LowerDate AND @UpperDate

    -- the third scenario - we use only DOB filter
    SELECT
        3 RowPriority, -- min priority
        ClientID,
        FirstName,
        LastName,
        VerificationCode,
        DOB
    FROM Client c
    WHERE (SELECT COUNT(*) FROM #SearchWords)=0
      AND DOB BETWEEN @LowerDate AND @UpperDate
  ) q
ORDER BY RowPriority

具有辅助变量的变体

-- an auxiliary variable
DECLARE @Scenario int=CASE
        WHEN (SELECT COUNT(*) FROM #SearchWords)>0 THEN IIF(@LowerDate IS NULL,1,2)
        WHEN (SELECT COUNT(*) FROM #SearchWords)=0 AND @LowerDate IS NOT NULL THEN 3
    END

SELECT
    ClientID,
    FirstName,
    LastName,
    VerificationCode,
    DOB
FROM Client c
WHERE
    (
        (
            @Scenario IN(1,2)
            AND EXISTS(
                  SELECT *
                  FROM #SearchWords s
                  WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
                     OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
                     OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
                )
        )
        OR
        @Scenario=3 -- this scenario doesn't use word filter
    )
  AND
    (
        (@Scenario IN(2,3) AND DOB BETWEEN @LowerDate AND @UpperDate)
        OR
        @Scenario=1 -- this scenario doesn't use DOB filter
    )