2012-04-18 26 views
0

我有两个表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, 
    branch  integer not null references Branches(id), 
    term  integer not null references Terms(id), 
    primary key (id) 
); 

和IM试图找到所有不重视他们的工作人员的作业。我会如何去做这件事?

+0

定义中缺少您在主键中使用的“course”列吗?并且'工作表'中缺少'id' .. – 2012-04-18 14:38:36

+0

如果您的代码示例中显示的表实际上可以通过复制/粘贴来创建,那么这会使那些试图回答您的人变得更容易。一点样本数据也不会伤害。将来,请在发布之前在空的测试数据库中尝试一下。 – kgrittn 2012-04-18 17:11:12

+0

@ErwinBrandstetter是的,这是我的坏,我复制并粘贴从旧表。 – SNpn 2012-04-19 04:12:14

回答

2

首先,解决您创建表的查询,像这样:

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的主科y应该使用jobid而不是courseid;
  • Job的第一列应该是id而不是cid;
  • 我推荐在使用对id列的引用时使用有意义的列名,如jobid

然后为您的查询,你需要这样的事:

SELECT * FROM Job 
WHERE id NOT IN (SELECT DISTINCT jobid FROM JobStaff); 
1

一种可能的方式:

SELECT * 
FROM job j 
LEFT JOIN jobstaff js ON js.job = j.id 
WHERE js.job IS NULL; 

我写了一个比较全面的答案这种问题就在昨天上dba.SE: https://dba.stackexchange.com/a/16651/3684

1

使用弗朗西斯普的答案的定义,但REFERENCES省略不定义的表,我的建议是(的变体从欧文Brandstetter修改的全面的答案的选项,他挂在他的回答)PostgreSQL的版本8.4或更高版本之一:

SELECT * 
    FROM Job j 
    WHERE NOT EXISTS (SELECT * FROM jobstaff js WHERE js.jobid = j.id); 

在最近版本的PostgreSQL,这将优化一样Erwin的回答,除了它只会显示Job的列,这似乎是你想要的。较窄的行(省略不需要的列)可能会在规模上稍微好一些。在较早版本的PostgreSQL中(版本8.4之前),使用Erwin答案中显示的选项可能会获得更好的性能;在8.4中添加了半连接和反连接优化,并且LEFT JOIN技巧是模拟它的最佳方式。

请注意,在这种情况下不需要DISTINCT

对于PostgreSQL中的这种情况,我建议不要使用NOT IN。虽然它在逻辑上并不重要,因为PRIMARY KEY约束会隐式地强制涉及的列到NOT NULL,NOT IN在涉及到NULL的列时会有令人惊讶的语义,并且处理这些语义的逻辑效率不如NOT EXISTSLEFT JOIN那样高效。 PostgreSQL不会刻录处理时间,以查看参数是否可证明为NOT NULL,因此无论如何您都会得到最差的优化。