2012-08-30 144 views
1

環境:Sql Server 2008另一種方法來寫這個sql

有一列包含逗號分隔值的行。

即使單個產品存在於該csv中,該如何獲取該行。

這是我如何做到的,但只是想知道是否有另一種方式來寫它?

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

回答

3

您當前的曲ery似乎並沒有準確地捕捉到你想要的結果。如果我們有這樣一排:

bananaberry cream pie,strawberry shortcake,orange juice 

這應該與您的查詢匹配嗎?我認爲這將是更準確:

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

如果你只是想找到一個項目,這可能是更有效的:

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

這一切說,我不知道這是任何比你有什麼更好的現在。

0

你可以使用分割功能(周圍有很多在網絡上),以ProductsCsv分成獨立的元素,然後進行比較,對香蕉,草莓等

理想情況下,你會不會保存CSV數據在一列中,但是有一個單獨的表。

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 Data Type Methods

nodes() Method (xml Data Type)

value() Method (xml Data Type)

Using Common Table Expressions

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+'%' 
相關問題