从SQL中选择行,其中列与字符串数组中的某些内容不匹配?

时间:2010-09-13 22:59:07

标签: sql sql-server sql-server-2005 tsql

假设我有一个表Product,其中包含一个名为ProductName的列,其值为:

Lawnmower
Weedwacker
Backhoe
Gas Can
Batmobile

现在,我在记事本中列出了应该从结果集中排除的产品,即:

Lawnmower
Weedwacker
Batmobile

在我的现实问题中,有成千上万的记录和成千上万的排除。在SQL Studio Manager中,如何构造类似于以下伪代码的查询,该伪代码只返回BackhoeGas Can作为结果?:

declare @excludedProductNames varchar(MAX) =
'Lawnmower
Weedwacker
Batmobile'

SELECT ProductName FROM Product
WHERE ProductName isn't in the list of @excludedProductNames

这只是一次性报告,所以我根本不关心表现。

3 个答案:

答案 0 :(得分:3)

首先要将这些单词放入SSMS中 - 您可以使用UNION ALL构建派生表:

SELECT 'Lawnmower' AS word
UNION ALL
SELECT 'Weedwacker'
UNION ALL
SELECT 'Batmobile'

这将返回一个包含单个列的表,名为“word”:

word
--------
Lawnmower
Weedwacker
Batmobile

买者

您需要转义数据中的任何单引号。 IE:O'Brian需要改为O''Brian - 只需加倍单引号就可以逃脱它。

现在,真正的查询...

使用NOT IN

有些数据库限制了IN中的条款数量,在数千个IIRC的某个地方,因此NOT EXISTSLEFT JOIN/IS NULL可能是更好的选择。

SELECT p.*
  FROM PRODUCT p
 WHERE p.productname NOT IN (SELECT 'Lawnmower' AS word
                             UNION ALL
                             SELECT 'Weedwacker'
                             UNION ALL
                             SELECT 'Batmobile'
                             ...)

使用NOT EXISTS

SELECT p.*
  FROM PRODUCT p
 WHERE NOT EXISTS (SELECT NULL
                     FROM (SELECT 'Lawnmower' AS word
                           UNION ALL
                           SELECT 'Weedwacker'
                           UNION ALL
                           SELECT 'Batmobile'
                           ...) x
                   WHERE x.word = p.productname)

使用LEFT JOIN / IS NULL

   SELECT p.*
     FROM PRODUCT p
LEFT JOIN (SELECT 'Lawnmower' AS word
           UNION ALL
           SELECT 'Weedwacker'
           UNION ALL
           SELECT 'Batmobile'
           ...) x ON x.word = p.productname
    WHERE x.word IS NULL

哪个最有效/最快?

如果比较的列不可为空,NOT IN or NOT EXIST are the best choice

答案 1 :(得分:1)

我认为你最好使用一些文本编辑器技巧来实现这一目标。例如,使用', '替换换行符,您可以轻松地进行select * from product where ProductName not in ('...', '...')查询。

答案 2 :(得分:0)

创建一个临时表,在那里加载所有排除项,并选择临时表中不存在的所有行。

-- create temp table #exclusions
select ProductName into #exclusions
from Product
where 1 = 2

# run a bunch of inserts
insert into #exclusions (ProductName) values ('LawnMower')
-- as many as needed...

# run your select
select * from Product
where ProductName not in (select Product from #exclusions)

drop table #exclusions

作为运行大量插入内容的替代方法,使用bcp将包含ProductNames的csv文件上传到非临时表中。