如果多个表中的另一个表引用了一个表,那么从两个表中获取数据的最快方法是什么?
考虑一个带有公司名称的表和一个带有合同的表。每个合同在每个组合中可以具有client
,intermediary
和contractor
。每个值可能是null
,同一公司在每个合同行中可能是一,二或三倍。
表定义为:
CREATE TABLE company (id integer,name text);
CREATE TABLE contract (id integer, client integer, intermediary integer, contractor integer);
我用下面的测试da创建了一个SQL提琴: 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,需要一个查询,该查询返回合同ID以及所涉及的每个公司的名称。子查询非常简单:
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]);
,
但是在这种情况下,丢失了哪家公司在合同中扮演的角色的信息。
(编辑:在现实世界中,有索引,外键约束和内容。为了简洁起见,我将所有内容都放在此处。)
答案 0 :(得分:1)
您的方法很好,尽管您应该使用表别名:
final location = new MyTestLocation();
debugPrint( location.toString() );
return new MaterialApp(
title: 'Welcome',
home: new Scaffold(
appBar: new AppBar(
title: new Text('appBarTitle'),
),
body: new Center(
child: new Text( location.myTestString ),
)
),
);
SELECT id,
(SELECT c.name FROM company c WHERE c.id = co.client) AS "clientName",
(SELECT c.name FROM company c WHERE c.id = co.intermediary) AS "intermediaryName",
(SELECT c.name FROM company c WHERE c.id = co.contractor) AS "contractorName"
FROM contract co;
应该是id
中的主键-或在其上建立索引。
您也可以使用company
来表达这一点:
left join
两种方法的性能应该非常相似。
答案 1 :(得分:0)
戈登的解决方案对我来说看起来不错(尤其是第二种解决方案,带有外部联接)。
您是否在表Contract中的Client,Intermediary和Contractor列上添加了外键和索引?