Внешнее соединение или динамический запрос, что лучше?
-
18-09-2019 - |
Вопрос
У меня есть следующие таблицы (я упростил данные, содержащиеся в таблицах).
RateTable
- rate_table_id [int]
- rate_table_name [nvarchar(50)]
RateTableUsed
- rate_used_id [int]
- rate_table_id [int] (key to RateTable.rate_table_id)
- customer_id [int]
RateTableExtra
- rate_table_extra_id [int]
- rate_ extra_id [int] (key to RateExtra.rate_table_id)
- rate_used_id [int] (key to RateTableUsed.rate_used_id)
RateExtra
- rate_ extra_id [int]
- rate_extra_name [nvarchar(50)]
select rate_table_name, rate_table_extra_id, rate_extra_name from RateTableUsed rtu
innerjoin RateTable rt on rtu.rate_table_id = rt.rate_table_id
innerjoin RateTableExtra rte on rte.rate_table_id = rt.rate_table_id
innerjoing RateExtr re on rte.rate_extra_id = re.rate_extra_id
RateExtra содержит только 3 значения с ключами 1, 2 и 3, а также названиями бензиновых сборов, платы за управление и GST.
Это отлично работает для своей текущей цели.Отображается список значений с совпадающими записями, а параметр RateExtra запрашивается только для имени_рейта_extra_name.
Итак, у меня могут быть следующие результаты:
- Тариф1, 1, БензинДоплата
- Таблица тарифов1, 2, Комиссия за управление
- Тариф2, 3, БензинДоплата
- Тарифная таблица4, 4, НДС
- Тарифная таблица6, 5, БензинДоплата
Меня попросили изменить это так, чтобы каждая возвращаемая запись теперь включала записи для каждого значения в таблице RateExtra.Если соответствующих записей нет, данные из моей таблицы RateTableExtra должны вернуться как NULL.Итак, мои данные должны вернуться как:
- Тариф1, 1, БензинДоплата
- Таблица тарифов1, 2, Комиссия за управление
- Таблица тарифов1, NULL, GST
- Тариф2, 3, БензинДоплата
- Таблица ставок2, NULL, плата за управление
- Таблица тарифов2, NULL, GST
- Таблица тарифов4, NULL, надбавка за бензин
- Таблица ставок4, NULL, плата за управление
- Тарифная таблица4, 4, НДС
- Тарифная таблица6, 5, БензинДоплата
- Таблица ставок6, NULL, плата за управление
- Таблица тарифов6, NULL, GST
Я пробовал соединения OUTER, но они, похоже, не работают, я предполагаю, потому что данные RateExtra связаны с RateTableExtra, который вернет ноль.Сейчас я подумываю о создании динамического запроса, который будет получать мой исходный набор результатов, перебирать его, проверяя скорость_extra_id и, если его еще нет в наборе результатов, добавлять новую строку к результатам с данными NULL там, где мне это нужно.Я предполагаю, что это сработает, но у меня такое ощущение, что это будет убийственно для производительности.
Есть ли лучший способ сделать это?Надеюсь, кто-то может помочь, это будет очень признательно.
Решение
Попробуй это:
select
rate_table_name,
rate_table_extra_id,
rate_extra
from
RateTableUsed rtu
inner join RateTable rt on
rtu.rate_table_id = rt.rate_table_id
cross join RateExtra re
left outer join RateTableExtra rte on
rte.rate_table_id = rt.rate_table_id
and rte.rate_extra_id = re.rate_extra_id
order by rt.rate_table_name, re.rate_extra_id
По сути, этот запрос представляет собой декартово соединение между RateTable
и RateExtra
, с left join
чтобы найти значения RateTableExtra
которые соответствуют этим парам.По сути, этот запрос возвращает все возможно комбинации RateTable
и RateExtra
, и покажем вам, какие из них есть у вас в RateTableExtra
стол быстро.
Будьте осторожны с декартовыми соединениями.Они могут очень быстро выйти из-под контроля за столами разумного размера!Наслаждаться!