#sql #postgresql
#sql #postgresql
Вопрос:
Возможно ли объединить таблицу, в которой имя таблицы является значением в столбце?
Здесь TABLE
вызывается food
:
id food_name price_table pricing_reference_id
1 | 'apple' | 'daily_price' | 13
2 | 'banana' | 'monthly_price' | 13
3 | 'hotdog' | 'weekly_price' | 17
4 | 'sandwich' | 'monthly_price' | 9
Есть еще три таблицы (таблицы ценообразования): daily_price
, weekly_price
, и monthly_price
таблицы.
Примечание: несмотря на их названия, три таблицы цен отображают совершенно разные виды информации, поэтому три таблицы не были объединены в одну таблицу
Каждая строка в food
таблице может быть объединена максимум с одной из трех таблиц ценообразования.
Следующее не работает — это просто для иллюстрации того, к чему я пытаюсь прийти:
SELECT *
FROM food
LEFT JOIN food.price_table ON food.pricing_reference_id = daily_price.id
WHERE id = 1;
Очевидно, что запрос не работает. Есть ли какой-либо способ, которым имя таблицы в price_table
столбце может использоваться в качестве имени таблицы при объединении?
Ответ №1:
Я бы предложил left join
s:
select f.*,
coalesce(dp.price, wp.price, mp.price) as price
from food f left join
daily_price dp
on f.pricing_reference_id = dp.id and
f.pricing_table = 'daily_price' left join
weekly_price wp
on f.pricing_reference_id = wp.id and
f.pricing_table = 'weekly_price' left join
monthly_price mp
on f.pricing_reference_id = mp.id and
f.pricing_table = 'monthly_price' ;
Для столбцов, на которые вы ссылаетесь, вам необходимо использовать coalesce()
для объединения результатов из трех таблиц. Вы говорите, что таблицы содержат разные данные, поэтому вам нужно будет перечислить столбцы отдельно.
Основная причина, по которой я рекомендую этот подход, — производительность. Я думаю left join
, что s должно быть быстрее, чем любое решение, которое использует union all
.
Ответ №2:
Не могли бы вы получить ожидаемый результат, используя производную таблицу, в UNION SELECT
которой есть столбец с именем каждой таблицы?
SELECT *
FROM food
LEFT JOIN
(
SELECT 'daily_price' AS price_table, * FROM daily_price
UNION ALL SELECT 'monthly_price', * FROM monthly_price
UNION ALL SELECT 'weekly_price', * FROM weekly_price
) t
ON food.price_table = t.price_table AND
food.pricing_reference_id = t.id
ORDER BY food.id;