Объединение таблицы с использованием значения столбца в качестве имени таблицы

#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;
  

dbfiddle