Попадание в список значений

Помнишь оператор IN из темы "Отсечение строк и сортировка"? Вот пример

SELECT *
  FROM store
 WHERE store_id IN (100, 300, 500)

В результат попадут магазины с идентификаторами 100, 300 и 500. Если store_id для строки равен одному из значений, перечисленных в IN, то условие принимает значение TRUE и строка попадает в результат.

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

Например, выведем информацию о товарах, которые доступны в магазинах дешевле 15000:

SELECT *
  FROM product p
 WHERE p.product_id IN (SELECT pp.product_id
                          FROM product_price pp
                         WHERE pp.price < 15000)
# product_id category_id name description
1 1 3 Пылесос S6 1400 вт
2 7 10 Deepbox Нейлон

Подзапрос

SELECT pp.product_id
  FROM product_price pp
 WHERE pp.price < 15000

вернет следующие строки

# product_id
1 1
2 1
3 1
4 7

Список значений внутри IN будет заменен на (1, 1, 1, 7).

Этот запрос можно переписать, используя JOIN + DISTINCT:

SELECT DISTINCT 
       p.*
  FROM product p
  JOIN product_price pp
    ON pp.product_id = p.product_id
 WHERE pp.price < 15000

Проверку IN можно выполнять по нескольким столбцам. Для этого их необходимо взять в скобки, а из подзапроса возвращать несколько столбцов. Выведем информацию о продуктах заказа, которые проданы по цене из каталога:

SELECT pi.*
  FROM purchase_item pi
  JOIN purchase p
    ON p.purchase_id = pi.purchase_id
 WHERE (pi.product_id, p.store_id, pi.price) IN
       (SELECT pp.product_id, pp.store_id, pp.price
          FROM product_price pp)

6.4 Подзапрос не вернул строк

6.6 Отсутствие в списке значений