Выберите строки из отфильтрованной части таблицы A, где столбец соответствует связи со столбцом из строки в таблице B, совпадающей по идентификатору

#sql #amazon-redshift

#sql #amazon-redshift

Вопрос:

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

Конкретно, у меня есть две таблицы, orders и product_info, к которым я обращаюсь через Amazon Redshift

Заказы

 | ID   | Date     | Amount | Region |
=====================================
| 1    | 2019/4/1 | $120   | A      |
| 1    | 2019/4/4 | $100   | A      |
| 2    | 2019/4/2 | $50    | A      |
| 3    | 2019/4/6 | $70    | B      |
 

Ключами порядка разделов являются регион и дата.

Информация о продукте

 | ID   | Release Date | Region |
| ---- | ------------ | ------ |
| 1    | 2019/4/2     | A      |
| 2    | 2019/4/3     | A      |
| 3    | 2019/4/5     | B      |
 

Первичный ключ информации о продукте — id, а ключ раздела — region .

Я хочу получить все строки из заказов в регионе A, где дата строки больше, чем значение даты выпуска в информации о продукте для этого идентификатора.

Таким образом, в этом случае он должен возвращать только одну строку,

 | 1    | 2019/4/4 | $100   | A      |
 

Я попытался сделать

 select *
from orders
INNER JOIN product_info ON orders.date>product_info.release_date
  AND orders.id=product_info.id
  AND orders.region=A
  AND product_info.region=A
limit 10
 

Проблема в том, что этот запрос был абсурдно медленным (отменен через 10 минут). Таблицы очень большие, и у меня такое ощущение, что он сканировал всю таблицу, не ограничивая ее сначала регионом (на самом деле у меня есть другие фильтры в дополнение к region, которые я хочу применить к списку идентификаторов, прежде чем выполнять внутреннее объединение, но я ограничил его только регионом дляради упрощения вопроса).

Как я могу эффективно написать этот тип запроса?

Комментарии:

1. Можете ли вы добавить свои определения таблиц, чтобы мы могли видеть, какие индексы у вас есть, и план объяснения.

2. Не могли бы вы уточнить, используете ли вы MySQL или Amazon Redshift? Возможности и синтаксис различаются в зависимости от двух систем.

3. Отредактировал вопрос, чтобы показать, что я использую Amazon Redshift.

Ответ №1:

Лучший способ ускорить SQL-запрос — исключить строки как можно скорее.

Таким образом, вместо того, чтобы ставить условия, как orders.region=A в инструкции JOIN, вы должны переместить их в WHERE инструкцию. Это приведет к удалению строк до их объединения.

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

Попробуйте что-то вроде этого:

 SELECT *
FROM orders
INNER JOIN product_info ON orders.id = product_info.id
WHERE orders.region = 'A'
  AND product_info.region = 'A'
  AND orders.date > product_info.release_date
 

Любая дальнейшая оптимизация потребует рассмотрения DISTKEY и SORTKEY в таблицах Redshift. (Предпочтительно a DISTKEY of id и a SORTKEY of date ).