MySQL - Сколько людей НЕ в объединенной таблице?

0

Я запускаю следующий запрос, который сообщает мне, какие агенты когда-либо планировались в проекте в местоположении 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);
Теги:
join

3 ответа

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 внешнего запроса.

  • 0
    Вы правы, они не нужны. И спасибо, это сработало на удивление хорошо.
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
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  
 )
  • 0
    Спасибо тебе за это. Это почти привело меня туда, но предложение group by заставило запрос выполняться почти семь минут. Удаление это сделало это работает отлично.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню