MySQL - 有多少人不在联合表中?

时间:2010-10-04 05:21:51

标签: mysql join

我正在运行以下查询,该查询告诉我在51号位置的项目上安排了哪些代理:

SELECT agents.agentid, agents.firstname, agents.lastname,
       schedule.projectid, projects.locationid
FROM agents
LEFT JOIN schedule USING (agentid)
LEFT JOIN projects USING (projectid)
WHERE (projects.locationid <=> 51)
GROUP BY agentid
ORDER BY agentid;

它产生1249行(这是正确的结果集)。

如果我想看到相反的情况,即没有在51位的项目上安排的代理,我将WHERE子句更改为:

WHERE NOT (projects.locationid <=> 51)

它产生16169行。 1249 + 16169 =比代理表中的行多。

很明显,因为代理商可以参与多个地点的项目,所以当这种情况发生时,他会出现在两个地方。

所以我的问题是,如何让第二个查询工作?也就是说,如何才能找出哪些代理商从未参与过51号位的项目?

感谢您的帮助!

编辑:以下是表格结构和示例数据:

CREATE TABLE IF NOT EXISTS `agents` (
`agentid` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
`firstname` VARCHAR(45) NOT NULL,
`lastname` VARCHAR(45) NOT NULL,
PRIMARY KEY (`agentid`));

CREATE TABLE IF NOT EXISTS `schedule` (
`scheduleid` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
`agentid` SMALLINT(5) UNSIGNED NOT NULL,
`projectid` SMALLINT(5) UNSIGNED NOT NULL,
PRIMARY KEY (`scheduleid`));

CREATE TABLE IF NOT EXISTS `projects` (
`projectid` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
`locationid` SMALLINT(5) UNSIGNED NOT NULL,
PRIMARY KEY (`projectid`));

INSERT INTO `agents` (`agentid`,`firstname`, `lastname`)
VALUES (1, 'Bob', 'Smith'), (2, 'John','Doe'), (3, 'Jane','Doe'), (4, 'Sam','Foo'), (5, 'Emily','Bar');

INSERT INTO `projects` (`projectid`, `locationid`)
VALUES (1, 51), (2, 12), (3,15), (4,51), (5,99), (6,21), (7,51);

INSERT INTO `schedule` (`scheduleid`, `agentid`, `projectid`)
VALUES (1, 1, 1), (2, 2, 3), (3, 4, 3), (4, 1, 6), (5, 3, 5), (6, 5, 1), (7, 5, 3), (8, 5, 7), (9, 3, 6), (10, 4, 4);

3 个答案:

答案 0 :(得分:1)

假设LEFT OUTER连接是必要的(我不相信),那么您需要不在上面获得的列表中的代理列表。因此:

SELECT agents.agentid, agents.firstname, agents.lastname
  FROM agents
 WHERE agentid NOT IN
       (SELECT agents.agentid
          FROM agents
          LEFT JOIN schedule USING (agentid)
          LEFT JOIN projects USING (projectid)
         WHERE (projects.locationid = 51)
       )
 ORDER BY agentid;

显然,如果您想知道这些代理涉及哪些项目,那么您将连接恢复到外部查询的FROM子句中。

答案 1 :(得分:0)

您可以使用IN子句。选择不在位置51中工作的业务代表列表中的所有业务代表:

SELECT
*
FROM agents
WHERE
agents.agentid NOT IN
 (
  SELECT agents.agentid
  FROM agents
  LEFT JOIN schedule USING (agentid)
  LEFT JOIN projects USING (projectid)
  WHERE (projects.locationid = 51)
  GROUP BY agentid
  ORDER BY agentid  
 )

答案 2 :(得分:0)

首先做一件事,在项目和计划表中添加索引。这将大大提高性能。然后尝试此查询

SELECT
*
FROM agents
LEFT JOIN 
 (
  SELECT agents.agentid, schedule.scheduleid,schedule.projectid, projects.locationid
  FROM agents
  LEFT JOIN SCHEDULE USING (agentid)
  LEFT JOIN projects USING (projectid)
  WHERE (projects.locationid = 51)
  GROUP BY agentid
  ORDER BY agentid  
 ) AS t
 ON agents.agentid = t.agentid
WHERE t.agentid IS NULL
相关问题