ПРЕДУПРЕЖДЕНИЕ О РЕШЕНИЯХ:
МНОГИЕ СУЩЕСТВУЮЩИЕ РЕШЕНИЯ ДАЮТ НЕПРАВИЛЬНЫЙ ВЫХОД, ЕСЛИ СТРОКИ НЕ УНИКАЛЬНЫ *
Если вы являетесь единственным человеком, создающим таблицы, это может быть неактуально, но несколько решений приведут к разному количеству выходных строк из рассматриваемого кода, когда одна из таблиц может не содержать уникальных строк.
ПРЕДУПРЕЖДЕНИЕ О ЗАЯВЛЕНИИ ЗАДАЧИ:
В С НЕСКОЛЬКИМИ КОЛОННАМИ НЕ СУЩЕСТВУЕТ, ВНИМАТЕЛЬНО ДУМАЙТЕ, ЧТО ВЫ ХОТИТЕ
Когда я вижу вход с двумя столбцами, я могу представить, что он означает две вещи:
- Значения столбца a и столбца b отображаются в другой таблице независимо
- Значения столбца a и столбца b появляются в другой таблице вместе в одной строке
Сценарий 1 довольно тривиален, просто используйте два оператора IN.
В соответствии с большинством существующих ответов, я настоящим предоставляю обзор упомянутых и дополнительных подходов к Сценарию 2 (и краткое суждение):
EXISTS (Безопасный, рекомендуется для SQL Server)
Как сказано в @mrdenny, EXISTS звучит именно так, как вы ищете, вот его пример:
SELECT * FROM T1
WHERE EXISTS
(SELECT * FROM T2
WHERE T1.a=T2.a and T1.b=T2.b)
LEFT SEMI JOIN (Безопасно, рекомендуется для диалектов, которые его поддерживают)
Это очень краткий способ присоединения, но, к сожалению, большинство диалектов SQL, включая SQL-сервер, в настоящее время не поддерживают его.
SELECT * FROM T1
LEFT SEMI JOIN T2 ON T1.a=T2.a and T1.b=T2.b
Несколько операторов IN (безопасно, но остерегайтесь дублирования кода)
Как уже упоминалось @cataclysm, использование двух операторов IN также может помочь, возможно, даже превзойдет другие решения. Тем не менее, вы должны быть очень осторожны с дублированием кода. Если вы когда-нибудь захотите выбрать из другой таблицы или изменить инструкцию where, это увеличит риск того, что вы создадите несоответствия в своей логике.
Базовое решение
SELECT * from T1
WHERE a IN (SELECT a FROM T2 WHERE something)
AND b IN (SELECT b FROM T2 WHERE something)
Решение без дублирования кода (я считаю, что это не работает в обычных запросах SQL Server)
WITH mytmp AS (SELECT a, b FROM T2 WHERE something);
SELECT * from T1
WHERE a IN (SELECT a FROM mytmp)
AND b IN (SELECT b FROM mytmp)
INNER JOIN (технически это можно сделать безопасным, но часто этого не делается)
Причина, по которой я не рекомендую использовать внутреннее объединение в качестве фильтра, заключается в том, что на практике люди часто допускают дубликаты в правой таблице, вызывая дубликаты в левой таблице. И что еще хуже, они иногда делают конечный результат отличным, в то время как левая таблица может фактически не быть уникальной (или не уникальной в выбранных вами столбцах). Кроме того, это дает вам возможность фактически выбрать столбец, который не существует в левой таблице.
SELECT T1.* FROM T1
INNER JOIN
(SELECT DISTINCT a, b FROM T2) AS T2sub
ON T1.a=T2sub.a AND T1.b=T2sub.b
Наиболее распространенные ошибки:
- Присоединение непосредственно к T2, без безопасного подзапроса. В результате возникает риск дублирования)
- SELECT * (гарантированно получить столбцы из T2)
- SELECT c (не гарантирует, что ваш столбец будет приходить и всегда будет поступать с T1)
- Нет DISTINCT или DISTINCT в неправильном месте
СЦЕПЛЕНИЕ КОЛОНН С СЕПАРАТОРОМ (Не очень безопасно, ужасная производительность)
Функциональная проблема заключается в том, что если вы используете разделитель, который может находиться в столбце, будет сложно убедиться, что результат на 100% точен. Техническая проблема заключается в том, что этот метод часто выполняет преобразования типов и полностью игнорирует индексы, что может привести к ужасной производительности.
Несмотря на эти проблемы, я должен признать, что иногда я все еще использую его для специальных запросов в небольших наборах данных.
SELECT * FROM T1
WHERE CONCAT(a,"_",b) IN
(SELECT CONCAT(a,"_",b) FROM T2)
Обратите внимание, что если ваши столбцы являются числовыми, некоторые диалекты SQL требуют, чтобы вы сначала приводили их к строкам. Я верю, что SQL-сервер сделает это автоматически.
Подводя итог: как обычно, есть много способов сделать это в SQL, использование безопасного выбора позволит избежать неожиданностей и сэкономить ваше время и трудности в долгосрочной перспективе.