0

昨日この問題に遭遇し、解決したと思っていましたが、間違っていました。このスクリプトでは、変数を区切り記号付きの文字列にする必要があります (これは、エンド ユーザーがアカウント タイトルの用語を検索するためです)。

たとえば、タイトルに「水」または「食品」が含まれている場合に、エンド ユーザーが検索したいとします。同じタイトルである必要はありません。結果は、「世界の水」と「思考の糧」を返す可能性があります。

いくつかの AND および OR ステートメントを使用してこれを簡単に記述できることを理解しています

 SELECT ...
 FROM ...
 WHERE 1=1
 and (rpt_title LIKE '%Food%' 
 or rpt_title LIKE '%Water%')

変数は 1 つのパラメーターのみを受け取りますが、文字列として受け取ります。(つまり、「食品 | 水」)。文字で区切られた文字列を取り、それを複数の変数に変換する関数が既にあります。これが解決策だとは思いません。substring と charindex を使用して区切り文字 (この場合はタイトルにない可能性が高いため、 | ) を見つけて、それを OR ステートメントに変換する必要があると思います。

何か考えや提案はありますか?

編集: 最終結果は、変数に入力する機能になります (例 - rpt_title LIKE '%'+@title+'%')

4

3 に答える 3

1

分割がそんなに悪い考えだと思う理由がわかりません。Numbers テーブルがあると仮定すると、比較的効率的なインライン TVF を作成し、それに対して結合できます。

CREATE FUNCTION dbo.SplitStrings_Numbers
(
   @List       NVARCHAR(MAX),
   @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN
   (
       SELECT Item = SUBSTRING(@List, Number, 
         CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number)
       FROM dbo.Numbers
       WHERE Number <= CONVERT(INT, LEN(@List))
         AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter)) = @Delimiter
   );
GO

(CLR などの絶対的に最も効率的なアプローチについては、http://www.sqlperformance.com/2012/07/t-sql-queries/split-strings を参照してください)

今、あなたは言うことができます:

SELECT t.rpt_title
  FROM dbo.table_name AS t
  INNER JOIN dbo.SplitStrings_Numbers(@Input, '|') AS x
  ON t.rpt_title LIKE '%' + x.Item + '%'
  GROUP BY t.rpt_title;

もう 1 つのアイデアはfoo|bar|splunge、最初のようにリストを使用するのではなく、TVP を使用することです。最初にテーブル タイプを作成します。

CREATE TYPE dbo.TitleMatches
(
  Pattern NVARCHAR(64)
);
GO

次に、それを使用するストアド プロシージャ:

CREATE PROCEDURE dbo.Whatever
  @matches dbo.TitleMatches READONLY
AS
BEGIN
  SET NOCOUNT ON;

  SELECT t.rpt_title
    FROM dbo.table_name AS t
    INNER JOIN @matches AS m
    ON t.rpt_title LIKE '%' + m.Pattern + '%'
    GROUP BY t.rpt_title;
END
GO

次に、DataTable を渡すか、潜在的な一致のリストを保持する構造体を渡すだけです。たとえば、C# では次のようになります。

DataTable DataTableName = new DataTable();

// ... populate data table here

SqlCommand cmd = new SqlCommand("dbo.Whatever", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvp = cmd.Parameters.AddWithValue("@matches", DataTableName);
tvp.SqlDbType = SqlDbType.Structured;

// ... execute, consume results, etc.

(詳細はhttp://www.sqlperformance.com/2012/08/t-sql-queries/splitting-strings-now-with-less-t-sqlを参照)

于 2013-03-27T13:36:11.167 に答える
0

以下に示すように、動的 tsql を使用する必要があるようです。残念ながら、サーバーでプリコンパイルできず、実行するたびに実行時に最適化する必要があるため、使用するのが効率的ではないことを何度も読みました。ただし、これはあなたが求めていることを達成するはずだと思います。これを実行するには、proc_DelimitedQuery 'aaa|bbb|etc' で呼び出します。

create PROCEDURE [dbo].[proc_DelimitedQuery]

@delimitedString varchar(100)
as

DECLARE @delimiter int
declare @pos int
DECLARE @item varchar(500)
Declare @criteria varchar(5000)

set @criteria = '(rpt_title like ''%'

set @pos=1

--find the first delimiter
SET @delimiter = CHARINDEX('|', @delimitedString, @pos)

WHILE @delimiter<>0
BEGIN
    set @item=substring(@delimitedString, @pos, @delimiter-@pos)
    set @criteria = @criteria + @item + '%'' or rpt_title like ''%'

    --Find the next delimiter
    set @pos=@delimiter+1

    if charindex('|', @delimitedString, @pos)=0
    begin

        set @pos=@delimiter+1
        set @item=substring(@delimitedString, @pos, datalength(@delimitedString)-@delimiter)
        set @criteria = @criteria + @item + '%'')'      
        set @delimiter=0
    end
    else
    begin
        set @delimiter=charindex('|', @delimitedString, @pos)
    end


END

declare @sql varchar(500)
set @sql='select * from MyTable where 1=1 and ' + @criteria

    --change the next line to select @sql if you want to examine the sql statement
EXECUTE(@sql)
GO
于 2013-03-27T14:45:13.030 に答える
0

これは少し汚れていますが、うまくいきました。申し訳ありませんが、私はしばらく TSQL を行っていません。

DECLARE @delim CHAR, @search NVARCHAR(100)
set @delim = '|'
set @search = 'world|food'

DECLARE @tblSearch TABLE(
string NVARCHAR(100)
)

DECLARE @tmpStr NVARCHAR(100)
WHILE (@search <> '')
BEGIN
    IF (CHARINDEX(@delim, @search) = 0)
        BEGIN
            INSERT INTO @tblSearch(string) VALUES('%' + @search + '%')
            SET @search = ''
        END
    ELSE
        BEGIN
            INSERT INTO @tblSearch(string)
            SELECT '%' + SUBSTRING(@search, 0, CHARINDEX(@delim, @search)) + '%'
            SET @search = SUBSTRING(@search, CHARINDEX(@delim, @search) + 1, LEN(@search))
        END
END

SELECT ...
FROM ... as m
INNER JOIN @tblSearch as s ON m.rpt_title like s.string
于 2013-03-27T14:18:12.373 に答える