postgresql查找唯一元组
我有两张桌子postgresql查找唯一元组,postgresql,Postgresql,我有两张桌子 create table JobStaff ( Job integer references Job(id), staff integer references Staff(id), role integer references JobRole(id), primary key (course,staff,role) ); create table Job ( cid integer,
create table JobStaff (
Job integer references Job(id),
staff integer references Staff(id),
role integer references JobRole(id),
primary key (course,staff,role)
);
create table Job (
cid integer,
branch integer not null references Branches(id),
term integer not null references Terms(id),
primary key (id)
);
我正在努力找到所有没有员工的工作。我该怎么做呢?一种可能的方法:
SELECT *
FROM job j
LEFT JOIN jobstaff js ON js.job = j.id
WHERE js.job IS NULL;
就在昨天,我在dba.SE上为这类问题写了一个更全面的答案:
一种可能的方法:
SELECT *
FROM job j
LEFT JOIN jobstaff js ON js.job = j.id
WHERE js.job IS NULL;
就在昨天,我在dba.SE上为这类问题写了一个更全面的答案:
首先,修复create table查询,如下所示:
create table JobStaff (
jobid integer references Job(id),
staffid integer references Staff(id),
roleid integer references JobRole(id),
primary key (jobid,staffid,roleid)
);
create table Job (
id integer,
branch integer not null references Branches(id),
term integer not null references Terms(id),
primary key (id)
);
的主键应该使用JobStaff
而不是jobid
李>courseid
的第一列应该是Job
,而不是id
李>cid
- 我建议在引用id列时使用有意义的列名,如
jobid
SELECT * FROM Job
WHERE id NOT IN (SELECT DISTINCT jobid FROM JobStaff);
首先,修复create table查询,如下所示:
create table JobStaff (
jobid integer references Job(id),
staffid integer references Staff(id),
roleid integer references JobRole(id),
primary key (jobid,staffid,roleid)
);
create table Job (
id integer,
branch integer not null references Branches(id),
term integer not null references Terms(id),
primary key (id)
);
的主键应该使用JobStaff
而不是jobid
李>courseid
的第一列应该是Job
,而不是id
李>cid
- 我建议在引用id列时使用有意义的列名,如
jobid
SELECT * FROM Job
WHERE id NOT IN (SELECT DISTINCT jobid FROM JobStaff);
使用Francis p答案中的定义,但由于未定义的表中省略了
参考
,我建议PostgreSQL 8.4版或更高版本使用此选项(他在答案中链接的Erwin Brandstetter综合答案中的一个选项的变体):
SELECT *
FROM Job j
WHERE NOT EXISTS (SELECT * FROM jobstaff js WHERE js.jobid = j.id);
在PostgreSQL的最新版本中,这将与Erwin answer的优化相同,只是它将只显示来自Job的列,这似乎是您想要的。较窄的行(省略不需要的列)可能在缩放时表现稍好。在较旧版本的PostgreSQL(8.4版之前)中,使用Erwin的答案中显示的选项,您可能会获得更好的性能;8.4中增加了半连接和反连接优化,而左连接
技巧是模拟它的最佳方法
请注意,在这种情况下不需要DISTINCT
对于PostgreSQL中的这种情况,我建议不要使用
而不是。虽然这在逻辑上并不重要,因为主键
约束会隐式强制所涉及的列为非NULL
,非IN
在涉及支持NULL的列时具有令人惊讶的语义,处理这些语义的逻辑不如不存在
或左连接
那么有效。PostgreSQL不会浪费处理时间来查看参数是否可证明不为空
,因此不管怎样,您都会得到较差的优化。使用Francis p的答案中的定义,但由于引用
忽略了未定义的表,我建议这样做(Erwin Brandstetter在其答案中链接到的综合答案中的一个选项的变体)对于PostgreSQL 8.4或更高版本:
SELECT *
FROM Job j
WHERE NOT EXISTS (SELECT * FROM jobstaff js WHERE js.jobid = j.id);
在最新版本的PostgreSQL中,这将与Erwin answer优化相同,只是它将仅显示作业中的列,这似乎是您想要的。较窄的行(忽略不需要的列)可能会在规模上表现稍好。在较旧版本的PostgreSQL中(8.4版之前)使用Erwin的答案中显示的选项,您可能会获得更好的性能;8.4中添加了半连接和反连接优化,而左连接
技巧是模拟它的最佳方法
请注意,在这种情况下不需要DISTINCT
对于PostgreSQL中的这种情况,我建议不要使用不在
中。虽然在逻辑上这并不重要,因为主键
约束会隐式地强制所涉及的列不为NULL
,不在
中有令人惊讶的语义,当涉及到能够为NULL的列时,处理这些列的逻辑会令人惊讶语义的效率不如not EXISTS
或LEFT JOIN
那么高。PostgreSQL不会花费处理时间来查看参数是否可证明不为NULL
,因此不管怎样,优化效果都很差。主键中使用的课程
列在定义中缺失?并且id
为空表作业中缺少。如果代码示例中显示的表实际上可以通过复制/粘贴来创建,则会使那些试图回答您的人的生活更轻松。一点示例数据也不会有任何影响。以后,请在发布前在空测试数据库中尝试。@ErwinBrandstetter是的,这是我的错误,我复制并粘贴了它d从旧表中删除。定义中缺少主键中使用的列course
,表job
中缺少id
。如果代码示例中显示的表实际上可以通过复制/粘贴来创建,则尝试回答您的人会更容易。少量示例数据也不会有任何影响。以后,请在发布之前在一个空的测试数据库中尝试一下。@ErwinBrandstetter是的,那是我的错,我从一个旧表复制并粘贴了它。