1

環境: SQL Server 2008

コンマ区切りの値を含む列の行があります。

そのcsvに単一の製品が存在する場合でも、行を取得するもの。

これは私ができる方法ですが、それを書く別の方法があるかどうか疑問に思っていましたか?

SELECT * FROM REWARDS
WHERE ProductCsv like '%banana%' 
   or ProductCsv like '%strawberry%' 
   or ProductCsv like '%orange%'
4

4 に答える 4

3

現在のクエリは、必要な結果を正確にキャプチャしていないようです。次のような行があるとします。

bananaberry cream pie,strawberry shortcake,orange juice

これはクエリに一致するかどうか。これはより正確だと思います:

WHERE ',' + ProductCsv + ',' LIKE '%,banana,%'
   OR ',' + ProductCsv + ',' LIKE '%,strawberry,%'
   OR ',' + ProductCsv + ',' LIKE '%,orange,%'

1 つのアイテムを見つけようとしているだけの場合は、おそらくこれがはるかに効率的です。

WHERE ',' + ProductCsv + ',' LIKE '%,banana,%'

おそらく、分割機能を使用する必要があります。例えば:

CREATE FUNCTION dbo.SplitStrings_XML
(
   @List   NVARCHAR(MAX),
   @Delim  NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN 
   (  
      SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
      FROM 
      ( 
        SELECT x = CONVERT(XML, '<i>' + REPLACE(@List, @Delim, '</i><i>') 
        + '</i>').query('.')
      ) AS a CROSS APPLY x.nodes('i') AS y(i)
   );
GO

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

SELECT * FROM dbo.REWARDS AS r
WHERE EXISTS 
(
  SELECT 1 FROM dbo.REWARDS AS r2
  CROSS APPLY dbo.SplitStrings_XML(r2.ProductCsv, ',') AS x
  WHERE x.Item IN ('orange','strawberry','banana')
  AND r2.[key] = r.[key]
);

またはもっと簡単に:

SELECT DISTINCT r.ProductCsv --, other columns
  FROM dbo.REWARDS AS r
  CROSS APPLY dbo.SplitStrings_XML(r.ProductCsv, ',') AS x
  WHERE x.Item IN ('orange','strawberry','banana');

XML アプローチは、テーブルに格納できる文字列の種類によっては少し脆弱ですが、多くの代替手段があります (リストまたは個別の値としてではなく、TVP を介してセットを渡すことを含む)。分割関数のより深い背景については、次のブログ投稿を参照してください。

http://www.sqlperformance.com/2012/07/t-sql-queries/split-strings

http://www.sqlperformance.com/2012/08/t-sql-queries/splitting-strings-follow-up

http://www.sqlperformance.com/2012/08/t-sql-queries/splitting-strings-now-with-less-t-sql

とはいえ、これがあなたが今持っているものよりも優れているかどうかはわかりません.

于 2012-08-30T04:11:31.123 に答える
1

比較するすべての値をテーブルに保存できます

DECLARE @Product_list TABLE(
        products VARCHAR(50)
)

Insert into @Product_list values
('banana'),
('strawberry'),
('orange')

SELECT * FROM REWARDS
join @Product_list
on ProductCsv like '%'+products+'%' 
于 2012-08-30T05:59:07.357 に答える
1

XML を使用した次の例を見てください。

DECLARE @Table TABLE(
        CommaList VARCHAR(MAX)
)

INSERT INTO @Table SELECT 'banana,test,hello'
INSERT INTO @Table SELECT 'homer,banana,test,hello'
INSERT INTO @Table SELECT 'homer,banana'
INSERT INTO @Table SELECT '1,2,3'

;WITH XMLValues AS (
        SELECT  *,
                CAST('<d>' + REPLACE(CommaList, ',', '</d><d>') + '</d>' AS XML) XMLValue
        FROM    @Table t
)
, SplitValues AS (
        SELECT  xv.*,
                T2.Loc.value('.','VARCHAR(MAX)') SplitValue
        FROM    XMLValues xv
        CROSS APPLY XMLValue.nodes('/d') as T2(Loc) 
)
SELECT  DISTINCT
        CommaList
FROM    SplitValues
WHERE   SplitValue = 'banana'

xml データ型メソッド

nodes() メソッド (xml データ型)

value() メソッド (xml データ型)

共通テーブル式の使用

于 2012-08-30T04:09:45.210 に答える
0

分割関数 (Web 上には多くの関数があります) を使用して、ProductsCsv を個々の要素に分割し、それをバナナやイチゴなどと比較できます。

理想的には、CSV データを列に格納するのではなく、別のテーブルを用意します。

于 2012-08-30T04:02:27.263 に答える