Выбрать строки из SQL, где столбец не совпадает с чем-то в массиве строк? - PullRequest
0 голосов
/ 14 сентября 2010

Допустим, у меня есть таблица, Product, со столбцом с именем ProductName, со значениями вроде:

Lawnmower
Weedwacker
Backhoe
Gas Can
Batmobile

Теперь у меня в Блокноте есть список продуктов, которые должны быть исключены из набора результатов, т. Е .:

.
Lawnmower
Weedwacker
Batmobile

В моей реальной проблеме есть десятки тысяч записей и тысячи исключений. В SQL Studio Manager, как я могу построить запрос, подобный следующему псевдокоду, который будет просто возвращать Backhoe и Gas Can в качестве результатов?:

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

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

Это единовременный отчет, поэтому мне не важна производительность.

Ответы [ 3 ]

3 голосов
/ 14 сентября 2010

Во-первых, эти слова попадают в 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 EXISTS или LEFT 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 или NOT EXIST - лучший выбор .

1 голос
/ 14 сентября 2010

Я думаю, что лучше всего использовать некоторые трюки в текстовом редакторе для достижения этой цели.например, замените символы новой строки на ', ', и вы можете легко выполнить запрос select * from product where ProductName not in ('...', '...').

0 голосов
/ 14 сентября 2010

Создайте временную таблицу, загрузите туда все свои исключения и выберите все строки, которых нет в временной таблице.

-- 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 для загрузки CSV-файла, содержащего ProductNames, во временную таблицу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...