У меня есть люди, компании и сотрудники. Каждая из этих таблиц имеет внешний ключ обратно к таблице, которую я называю сторонами, которая поддерживает одноуровневую запись через триггеры. Стороны имеют от 0 до N site_locators, которые сами ссылаются на сайты, которые ссылаются на города.
Я создаю представление, которое возвращает полное имя адресата и его город. Код в таком виде:
SELECT
surname
, rest_of_name
, 'Employee' AS party_type_code
, party_id
, cities.name AS city_name
FROM
employees
LEFT JOIN site_locators USING (party_id)
LEFT JOIN sites USING (site_id)
LEFT JOIN cities USING (city_id)
UNION ALL
SELECT
surname
, NULL::text
, 'Company' AS party_type_code
, party_id
, cities.name AS city_name
FROM
companies
LEFT JOIN site_locators USING (party_id)
LEFT JOIN sites USING (site_id)
LEFT JOIN cities USING (city_id)
UNION ALL
SELECT
surname
, rest_of_name
, 'Person' AS party_type_code
, party_id
, cities.name AS city_name
FROM
people
LEFT JOIN site_locators USING (party_id)
LEFT JOIN sites USING (site_id)
LEFT JOIN cities USING (city_id)
Мне не очень нравятся множественные ЛЕВЫЕ СОЕДИНЕНИЯ в каждом СОЮЗЕ. Я реорганизовал код, чтобы выполнить СОЕДИНЕНИЕ только один раз как отдельный шаг:
SELECT
parties.*
, cities.name AS city_name
FROM (
SELECT /* As above, minus city_name */
FROM employees
UNION ALL
SELECT /* As above, minus city_name */
FROM companies
UNION ALL
SELECT /* As above, minus city_name */
FROM people
) AS parties
LEFT JOIN site_locators USING (party_id)
LEFT JOIN sites USING (site_id)
LEFT JOIN cities USING (city_id)
Этот второй запрос выполняется быстрее, потому что СОЕДИНЕНИЯ происходят только один раз после фильтрации всех таблиц. Что мне интересно, так это то, что если я смогу провести дальнейший рефакторинг, чтобы, если site_locators не возвращал строки для вечеринки, мне даже не нужно было искать сайты или города? Мне интересно, если это можно переписать с некоторыми внутренними соединениями, а не со всеми левыми соединениями. У меня был неудачный опыт работы с левыми соединениями, и я хочу сократить их количество.
ПРИМЕЧАНИЕ. Таблица сторон существует для уменьшения количества таблиц. Если бы его не было, мне бы понадобились таблицы для каждого типа группы и типа локатора: employee_site_locators, people_site_locators, company_site_locators, employee_email_locators, people_email_locators и так далее. С таблицей сторон у меня может быть одна таблица * _locator для каждого типа локатора.