0

私は2つのテーブルを持っています

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 クエリを修正します。

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
  • jobidid 列への参照を使用する場合のように、意味のある列名を使用することをお勧めします。

次に、クエリには次のようなものが必要です。

SELECT * FROM Job
WHERE id NOT IN (SELECT DISTINCT jobid FROM JobStaff);
于 2012-04-18T14:40:42.683 に答える
1

Francis P の回答の定義を使用しますが、定義REFERENCESされていないテーブルを省略して、PostgreSQL バージョン 8.4 以降の場合は、これ (彼が回答でリンクした Erwin Brandstetter の包括的な回答からのオプションの 1 つの変形) をお勧めします。

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この場合は不要であることに注意してください。

NOT INPostgreSQL でのこのようなケースには反対することをお勧めします。ここでは論理的には問題ではありませんが、PRIMARY KEY制約によって関係する列が暗黙的に に強制されるためNOT NULL、 にNOT INは NULL 可能な列が関係する場合に驚くべきセマンティクスがあり、これらのセマンティクスを処理するロジックはNOT EXISTSやほど効率的ではありませんLEFT JOIN。PostgreSQL は、引数が probablyNOT NULLであるかどうかを確認するために処理時間を消費しないため、最適化に関係なく貧弱な結果が得られます。

于 2012-04-18T17:08:26.120 に答える
1

考えられる方法の 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 に答える