0

这是一个指向当前有效的小提琴的链接,似乎有更好的方法可以做到这一点,我没有看到:http ://sqlfiddle.com/#!2/396f2/6

--- Sample schema
CREATE TABLE `jobs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `salary` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `people` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `people_jobs` (
  `pid` int(11) NOT NULL DEFAULT '0',
  `jid` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`pid`,`jid`),
  KEY `jid` (`jid`),
  CONSTRAINT `people_jobs_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `people` (`id`),
  CONSTRAINT `people_jobs_ibfk_2` FOREIGN KEY (`jid`) REFERENCES `jobs` (`id`)
);

这是查询

SELECT p.name, j.title FROM people p LEFT JOIN
 people_jobs pj ON pj.pid = p.id LEFT JOIN
 jobs j ON j.id = pj.jid WHERE p.id NOT IN
(SELECT p.id FROM people p INNER JOIN
 people_jobs pj ON pj.pid = p.id INNER JOIN
 jobs j ON j.id = pj.jid WHERE j.title = 'Artist');

有没有办法用 LEFT JOIN 做到这一点?这就是我通常会如何查找表中不存在的内容的方式。但在这种情况下,我正在寻找不存在或与特定工作不匹配的东西。我翻了很多遍,但找不到任何基于不在表格中或匹配特定条件的排除示例。

我想找回不是艺术家的人及其相关工作(如果他们没有工作,则为空)。因此,如果某人有 5 个工作,但其中之一是“艺术家”,我想将该人完全排除在列表之外。

4

3 回答 3

1

我不确定您将如何在没有嵌套子查询的情况下使用查询来排除艺术家,但一个小的优化是在您的子查询中删除不必要的人员连接,即

SELECT p.name, j.title 
  FROM people p 
  LEFT JOIN people_jobs pj ON pj.pid = p.id 
  LEFT JOIN jobs j ON j.id = pj.jid 
 WHERE p.id NOT IN
   (SELECT pj.pid 
      FROM people_jobs pj 
     INNER JOIN jobs j ON j.id = pj.jid 
     WHERE j.title = 'Artist')
于 2013-10-28T23:16:13.190 回答
1

建立你想要的结果集(people to people_jobs to jobs),然后离开加入people_jobs第二次,这里的人是一样的,但工作总是“艺术家”。过滤掉生成的非空行,因为这些人是从事艺术家工作的人。

例如

SELECT p.name, j.title
FROM people p
LEFT JOIN (
    people_jobs pj
    JOIN jobs j ON j.id = pj.jid
) ON pj.pid = p.id
LEFT JOIN people_jobs artists ON artists.pid = p.id AND artists.jid = 5
WHERE artists.pid IS NULL

这假设您提前知道(或可以获得)艺术家的工作 ID,并且它是5. 如果没有,您可以执行另一个嵌套连接或子查询以按名称查找作业。

于 2013-10-28T23:06:29.643 回答
-1

我想你可以试试这个:

select
  p.name, j.title
from
  people as p
  left join people_jobs as pj on p.id = pj.pid
  left join jobs as j on j.id = pj.jid
  left join (
    select 
      p.Id
    from
      people as p
      inner join people_jobs pj on p.id = pj.pid
      inner join jobs as j on pj.jid = j.id
    where
      j.title = 'Artist'
  ) as a on p.id = a.id
where
  a.id is null;

您可以将条件放在 aleft join而不是where条件中。

试试(新的)更新的 SQL Fiddle

如果您的表很大,也许您可​​以考虑创建一个临时表并使用它而不是子查询:

drop table if exists temp_condition;
create temporary table temp_condition
    select distinct
      p.Id
    from
      people as p
      inner join people_jobs pj on p.id = pj.pid
      inner join jobs as j on pj.jid = j.id
    where
      j.title = 'Artist';
alter table temp_condition
    add unique index idx_id(Id);
select
  p.name, j.title
from
  people as p
  left join people_jobs as pj on p.id = pj.pid
  left join jobs as j on j.id = pj.jid
  left join temp_condition as a on p.id = a.id
where
  a.id is null;

希望这对现在有帮助

于 2013-10-28T23:12:00.180 回答