如何使用 like(或欢迎使用不同的解决方案)搜索除某些字符串以外的所有字符串?
How to search for all except certain strings using like (or different solution welcomed)?
现在,我需要过滤掉包含特定文本字符串的行。
例如。对于以这种格式给出的字符串:'taxes, car' - 我需要过滤掉行描述中包含 "taxes" 或 "cars" 的所有行。
我想出了这个:
SELECT
TransactionId
,t.DocumentID
,t.DocumentDescription
FROM [Transaction] t
INNER JOIN (SELECT CONCAT('%',[Value], '%') AS [Value]
FROM STRING_SPLIT(N'taxes,cars',',')
) w
ON t.[DocumentDescription] NOT LIKE w.[Value]
这根本不起作用,因为它匹配两个拆分的字符串,并且仅当两个字符串都包含在行的描述中时才过滤掉该行。
任何想法如何使它工作?
我想你想要 NOT EXISTS
:
WITH w as (
SELECT value as word
FROM STRING_SPLIT(N'taxes,cars', ',')
)
SELECT t.*
FROM [Transaction] t
WHERE NOT EXISTS (SELECT 1
FROM w
WHERE t.DocumentDescription LIKE CONCAT('%', w.word, '%')
);
请注意,由于使用 LIKE
,此查询必须扫描整个 table。您可能需要重新考虑您的数据模型,如果 table 很大并且性能是个问题,也许可以使用全文索引或将描述分解为单词。
既然你说你对其他想法持开放态度......你想要做的事情可以在没有拆分器功能的情况下完成(例如 STRING_SPLIT 在你的例子中)。如果你想让你的过滤器表达式 ('taxes,cars'
) 作为参数出现,那么你可以使用 SRING_SPLIT。请注意示例数据和下面的两个示例:
DECLARE @Transaction TABLE
(
TransactionId INT IDENTITY,
DocumentDescription VARCHAR(1000)
);
INSERT @Transaction (DocumentDescription) VALUES('Blah, blah... cars...'), ('Yada, yada... taxes'),('Blah blah...');
-- Without a Splitter Function (e.g. SPLIT_STRING)
SELECT t.TransactionId, t.DocumentDescription
FROM @Transaction AS t
WHERE NOT EXISTS
(
SELECT 1
FROM @Transaction
CROSS JOIN (VALUES('taxes'),('cars')) AS srch(Item)
WHERE CHARINDEX(srch.Item,t.DocumentDescription) > 0
);
-- Using Split String
SELECT t.*
FROM @Transaction AS t
WHERE NOT EXISTS
(
SELECT 1
FROM STRING_SPLIT(N'taxes,cars', ',') AS w
WHERE CHARINDEX(w.[value],DocumentDescription) > 0
);
这让我得到了我想要的结果!
SELECT 1,2,3 FROM [Transaction]
EXCEPT
SELECT 1,2,3 FROM [Transaction] t
INNER JOIN (INNER JOIN(SELECT CONCAT('%',[Value], '%') AS [Value] FROM
STRING_SPLIT(N'cars,taxes',',')) w
ON t.Description LIKE w.Value
现在,我需要过滤掉包含特定文本字符串的行。 例如。对于以这种格式给出的字符串:'taxes, car' - 我需要过滤掉行描述中包含 "taxes" 或 "cars" 的所有行。 我想出了这个:
SELECT
TransactionId
,t.DocumentID
,t.DocumentDescription
FROM [Transaction] t
INNER JOIN (SELECT CONCAT('%',[Value], '%') AS [Value]
FROM STRING_SPLIT(N'taxes,cars',',')
) w
ON t.[DocumentDescription] NOT LIKE w.[Value]
这根本不起作用,因为它匹配两个拆分的字符串,并且仅当两个字符串都包含在行的描述中时才过滤掉该行。 任何想法如何使它工作?
我想你想要 NOT EXISTS
:
WITH w as (
SELECT value as word
FROM STRING_SPLIT(N'taxes,cars', ',')
)
SELECT t.*
FROM [Transaction] t
WHERE NOT EXISTS (SELECT 1
FROM w
WHERE t.DocumentDescription LIKE CONCAT('%', w.word, '%')
);
请注意,由于使用 LIKE
,此查询必须扫描整个 table。您可能需要重新考虑您的数据模型,如果 table 很大并且性能是个问题,也许可以使用全文索引或将描述分解为单词。
既然你说你对其他想法持开放态度......你想要做的事情可以在没有拆分器功能的情况下完成(例如 STRING_SPLIT 在你的例子中)。如果你想让你的过滤器表达式 ('taxes,cars'
) 作为参数出现,那么你可以使用 SRING_SPLIT。请注意示例数据和下面的两个示例:
DECLARE @Transaction TABLE
(
TransactionId INT IDENTITY,
DocumentDescription VARCHAR(1000)
);
INSERT @Transaction (DocumentDescription) VALUES('Blah, blah... cars...'), ('Yada, yada... taxes'),('Blah blah...');
-- Without a Splitter Function (e.g. SPLIT_STRING)
SELECT t.TransactionId, t.DocumentDescription
FROM @Transaction AS t
WHERE NOT EXISTS
(
SELECT 1
FROM @Transaction
CROSS JOIN (VALUES('taxes'),('cars')) AS srch(Item)
WHERE CHARINDEX(srch.Item,t.DocumentDescription) > 0
);
-- Using Split String
SELECT t.*
FROM @Transaction AS t
WHERE NOT EXISTS
(
SELECT 1
FROM STRING_SPLIT(N'taxes,cars', ',') AS w
WHERE CHARINDEX(w.[value],DocumentDescription) > 0
);
这让我得到了我想要的结果!
SELECT 1,2,3 FROM [Transaction]
EXCEPT
SELECT 1,2,3 FROM [Transaction] t
INNER JOIN (INNER JOIN(SELECT CONCAT('%',[Value], '%') AS [Value] FROM
STRING_SPLIT(N'cars,taxes',',')) w
ON t.Description LIKE w.Value