Какой самый быстрый способ извлечения данных из двух таблиц, если на одну таблицу ссылаются из другой в нескольких столбцах?
Рассмотрим таблицу с названиями компаний и таблицу с контрактами.Каждый контракт может иметь client
, intermediary
и contractor
- в каждой комбинации.Каждое значение может быть null
, а одна и та же компания может быть один, два или три раза в каждой строке контракта.
Определения таблицы:
CREATE TABLE company (id integer,name text);
CREATE TABLE contract (id integer, client integer, intermediary integer, contractor integer);
Я создал скрипту SQL с тестом da ниже: https://www.db -fiddle.com / f / irCodeZjeEPWvhmRwMcHqT / 0
Тестовые данные:
INSERT INTO company (id,name) VAlUES (1,'Company 1');
INSERT INTO company (id,name) VAlUES (2,'Company 2');
INSERT INTO company (id,name) VAlUES (3,'Company 3');
INSERT INTO company (id,name) VAlUES (4,'Company 4');
INSERT INTO company (id,name) VAlUES (5,'Company 5');
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (1,NULL,NULL,NULL);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (2,NULL,2,3);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (3,1,NULL,NULL);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (4,NULL,2,NULL);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (5,1,2,3);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (6,4,NULL,5);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (7,1,NULL,1);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (7,3,3,3);
Теперь, используя PostgreSQL 9.6, необходим запрос, который возвращает идентификатор контракта с названием каждой участвующей компании.Довольно просто с подзапросами:
SELECT
id,
(SELECT name FROM company WHERE id = client) AS "clientName",
(SELECT name FROM company WHERE id = intermediary) AS "intermediaryName",
(SELECT name FROM company WHERE id = contractor) AS "contractorName"
FROM contract;
Однако в реальном мире с гораздо более сложным запросом мы сталкиваемся здесь с проблемами производительности.Вопрос сейчас: есть ли способ улучшить его?JOIN
будет быстрее, чем подзапросы?Если да: как это вообще сработает?
Конечно, вы могли бы сделать что-то вроде
SELECT * FROM contract LEFT JOIN company ON company.id = ANY(ARRAY[client,contractor,intermediary]);
,
, но в этом случае информация, которую компания играет, какаяроль в контракте теряется.
(Правка: В реальном мире существуют индексы, ограничения внешнего ключа и прочее. Я оставил все это здесь для краткости.)