Я пытаюсь выяснить, как исключить элементы из оператора select из таблицы A, используя список исключений из таблицы B. Уловка заключается в том, что я исключаю на основе префикса поля.
Таким образом, значение поля может быть «FORD Muffler», и чтобы исключить его из базового запроса, я бы сделал:
SELECT FieldName
FROM TableName
WHERE UPPER(ColumnName) NOT LIKE 'FORD%'
Но чтобы использовать список значений для исключения из другой таблицы, я бы использовал подзапрос, например:
SELECT FieldName
FROM TableName
WHERE UPPER(ColumnName) NOT IN (Select FieldName2 FROM TableName2)
Проблема в том, что он исключает только точные совпадения, а не LIKE или подстановочные знаки (%).
Как я могу выполнить эту задачу? Изменение дизайна таблицы не является вариантом, поскольку это уже существующая таблица.
Обновлено: Извините, я использую SQL Server (2005).
Они могут быть разной длины.
Джоэл дал хороший ответ, но я просто отмечу, что необходимость искать подстроку для сравнения между таблицами - это большой красный флаг для проблемы проектирования базы данных. Я не знаю подробностей, поэтому не могу сказать, но вы можете просмотреть это, имея в виду, что столбец должен содержать только один факт.


Думаю, это сработает:
SELECT FieldName
FROM TableName
LEFT JOIN TableName2 ON UPPER(ColumnName) LIKE TableName2.FieldName2 + '%'
WHERE TableName2.FieldName2 IS NULL
Почему у вас WHERE TableName2.FieldName2 IS NULL? Казалось бы, это противоречит цели объединения.
Это связано с тем, что ему нужны только те записи, которые НЕ имеют совпадений для соединения. Поскольку это левое внешнее соединение, записи из первой таблицы по-прежнему доступны при применении фильтра where. Записи из 2-й таблицы просто имеют нулевые значения.
Другими словами, INNER-соединение вернет в точности противоположное тому, что он хочет: записи, в которых 1-я таблица ЕСТЬ как 2-я. ВНЕШНЕЕ соединение без предложения where вернет ОБА: записи, которые соответствуют И не совпадают. Затем добавьте это предложение where, и мы вернемся только к записям, которые НЕ совпадают.
Не знаю, насколько это будет эффективно, но должно работать:
SELECT FieldName
FROM TableName t1
WHERE NOT EXISTS (
SELECT *
FROM TableName2 t2
WHERE t1.FieldName LIKE t2.FieldName2 + '%'
)
Я бы изменил это на «выберите 1», а не «выберите *», поскольку нет смысла извлекать все поля, поскольку вы их не используете.
Присоединиться, как правило, быстрее, но, конечно, вам всегда нужно иметь профиль, чтобы знать наверняка.
Оптимизатор запросов, вероятно, все равно его оптимизирует.
@Garry Я сам всегда использую "1" в подзапросах "EXISTS", но подумал, что это может сбить с толку людей в этом ответе. Я не уверен, что это имеет значение для более продвинутых механизмов SQL.
@ рекурсивно должно, но не всегда. В этом случае переписать просто, но они могут стать довольно сложными, поскольку любой произвольный запрос может находиться внутри «существует», и неясно, как оценивать стоимость существующего списка по сравнению с объединением. Так что оптимизатор может этого не увидеть. Особенно оптимизатор mysql ...
SELECT * FROM table_A
LEFT OUTER JOIN table_B
ON (locate(table_b.column, UPPER(table_a.column)) == 1)
WHERE table_b.column IS NULL
Являются ли значения в таблице 2 фиксированной длиной или переменной?