0

我有两张桌子

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)
);

我试图找到所有没有员工的工作。我该怎么做呢?

4

3 回答 3

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的主键应该使用jobid而不是courseid;
  • Job的第一列应该id代替cid;
  • 我建议使用有意义的列名,例如jobid在使用对 id 列的引用时。

然后对于您的查询,您将需要这样的东西:

SELECT * FROM Job
WHERE id NOT IN (SELECT DISTINCT jobid FROM JobStaff);
于 2012-04-18T14:40:42.683 回答
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

于 2012-04-18T14:34:25.770 回答
1

使用 Francis P 的答案中的定义,但REFERENCES省略了未定义的表,我建议 PostgreSQL 版本 8.4 或更高版本(Erwin Brandstetter 的综合答案中的一个选项的变体,他在他的答案中链接到):

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,但当涉及 NULL 列时具有令人惊讶的语义,并且处理这些语义的NOT IN逻辑不如. PostgreSQL 不会消耗处理时间来查看参数是否可证明,所以无论如何你都会得到糟糕的优化。NOT EXISTSLEFT JOINNOT NULL

于 2012-04-18T17:08:26.120 回答