SQL Server:返回表中包含多个字符串的行

时间:2018-12-13 18:04:41

标签: sql-server tsql

我正在尝试检索包含在存储过程参数中传递的任何逗号分隔字符串的所有行。但是我的代码中的问题在于,它返回包含逗号分隔字符串的任何的所有行,而不是 all 逗号分隔的字符串。

下面的代码只有2个字符串,但是可能会有许多逗号分隔的字符串。 在现实世界中,用户可以有多个列,并且我应该能够在该表中搜索多个以逗号分隔的字符串。因此,我的存储过程应该返回包含所有用逗号分隔的搜索字符串的行。

表格:

Exchange    Ticker
------------------
NASDAQ      GOOG
NASDAQ      APPL
NASDAQ      MSFT
NYSE        IBM
NASDAQ      AMZN
NYSE        FB

存储过程代码:

DECLARE @searchStr VARCHAR(500) = 'NASDAQ,GOOG'

CREATE TABLE #TSearchString (tempStr VARCHAR(100))

WHILE LEN(@searchStr) > 0
BEGIN
    DECLARE @temp VARCHAR(100)

    IF CHARINDEX(',',@searchStr) > 0
        SET @temp = SUBSTRING(@searchStr, 0, CHARINDEX(',', @searchStr))
    ELSE
    BEGIN
        SET @temp = @searchStr
        SET @searchStr = ''
    END

    INSERT INTO #TSearchString 
    VALUES (@temp)

    SET @searchStr = REPLACE(@searchStr,@temp + ',' , '')
 END

 SELECT * 
 FROM stocks 
 WHERE Exchange IN (SELECT tempStr FROM #TSearchString) 
    OR ticker IN (SELECT tempStr FROM #TSearchString)

当前结果:

Exchange    ticker
-------------------
NASDAQ      GOOG
NASDAQ      APPL
NASDAQ      MSFT
NASDAQ      AMZN

预期结果:

Exchange    ticker
-------------------
NASDAQ      GOOG

DECLARE @searchStr VARCHAR(500) = 'NASDAQ'的预期结果是存储过程应返回所有包含“ NASDAQ”的行时。

Exchange    ticker
--------------------
NASDAQ      GOOG
NASDAQ      APPL
NASDAQ      MSFT
NASDAQ      AMZN

2 个答案:

答案 0 :(得分:0)

您在寻找

DECLARE @searchStr VARCHAR(500) = 'NASDAQ,GOOG';

SELECT *
FROM T 
WHERE T.Exchange = LEFT(@searchStr, CHARINDEX(',', @searchStr) - 1)
AND T.Ticker = RIGHT(@searchStr, CHARINDEX(',', @searchStr)-3)

DECLARE @searchStr VARCHAR(500) = 'NASDAQ,GOOG,NYSE,IBM';

SELECT T.*
FROM
  (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) RN,
          value V
   FROM STRING_SPLIT(@searchStr, ',')
  ) T1 JOIN
  (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) RN,
          value V
   FROM STRING_SPLIT(@searchStr, ',')
  ) T2
  ON T1.RN + 1 = T2.RN
  JOIN T
  ON T.Exchange = T1.V
     AND
     T.Ticker = T2.V;

更新:

SELECT *
FROM T 
WHERE 
( 
    CASE WHEN CHARINDEX(',', @searchStr) > 0 
         THEN LEFT(@searchStr, CHARINDEX(',', @searchStr) - 1)
         ELSE @searchStr
    END = T. Exchange
)
AND
(
  (T.Ticker IS NOT NULL AND CHARINDEX(',', @searchStr) = 0)
  OR
  (
    CASE WHEN CHARINDEX(',', @searchStr) > 0
         THEN RIGHT(@searchStr, CHARINDEX(',', @searchStr)-3)
         END = T.Ticker
  )
)

Demo

您可以创建类似的功能

CREATE FUNCTION MyFunc 
(@searchStr VARCHAR(500))
RETURNS TABLE
AS
RETURN
  SELECT *
  FROM T 
  WHERE 
  ( 
      CASE WHEN CHARINDEX(',', @searchStr) > 0 
           THEN LEFT(@searchStr, CHARINDEX(',', @searchStr) - 1)
           ELSE @searchStr
      END = T. Exchange
  )
  AND
  (
    (T.Ticker IS NOT NULL AND CHARINDEX(',', @searchStr) = 0)
    OR
    (
      CASE WHEN CHARINDEX(',', @searchStr) > 0
           THEN RIGHT(@searchStr, CHARINDEX(',', @searchStr)-3)
           END = T.Ticker
    )
  )

然后

SELECT * FROM dbo.MyFunc('NYSE');
SELECT * FROM dbo.MyFunc('NASDAQ,GOOG');

Demo


  

最后,如果这不符合您的要求,则建议您使用 Table-Valued Parameter 而不是逗号分隔的字符串。

答案 1 :(得分:-2)

这是我想出的答案,虽然效率不高,但是可以解决问题

DECLARE @searchStr VARCHAR(500) = 'NASDAQ,GOOG'
create table #TempOne (Exchange varchar(50), ticker varchar(10))
create table #TempTwo (Exchange varchar(50), ticker varchar(10))
insert into #TempOne select * from stocks
WHILE LEN(@searchStr) > 0
BEGIN
    DECLARE @temp VARCHAR(100)
    IF CHARINDEX(',',@searchStr) > 0
        SET @temp = SUBSTRING(@searchStr, 0, CHARINDEX(',', @searchStr))
    ELSE
    BEGIN
        SET @temp = @searchStr
        SET @searchStr = ''
    END
    Declare @temp1 varchar(100)
    set @temp1 = '%'+ @temp + '%'
    insert into #TempTwo select * from #TempOne where ticker like @temp1 or Exchange like @temp1
    delete #TempOne
    insert into #TempOne select * from #TempTwo
    delete #TempTwo
    SET @searchStr = REPLACE(@searchStr,@temp + ',' , '')
 END

 select * from #TempOne