значения «в» и «не в» не суммируются - что не так? - PullRequest
2 голосов
/ 10 октября 2009

У меня есть несколько серверов. Некоторым из них назначен ips. Я хочу выяснить, сколько нет. Очевидно, что серверов больше, чем назначенных ips, но моя база данных сообщает, что нет серверов, для которых не назначен ips ...

Я нахожусь в конце моего остроумия здесь. Моя БД повреждена каким-то странным образом?

SELECT COUNT(*) 
  FROM server

... возвращается:

+----------+
| count(*) |
+----------+
|    23088 | 
+----------+
1 row in set (0.00 sec)

Это:

SELECT COUNT(*) 
  FROM server 
 WHERE server_id IN (SELECT DISTINCT(server_id) 
                       FROM ips)

... возвращается:

+----------+
| count(*) |
+----------+
|    13811 | 
+----------+
1 row in set (0.01 sec)

Это:

SELECT COUNT(*) 
  FROM server 
 WHERE server_id NOT IN (SELECT DISTINCT(server_id) 
                           FROM ips);

... возвращается:

+----------+
| count(*) |
+----------+
|        0 | 
+----------+
1 row in set (0.02 sec)

Результаты были отредактированы, чтобы защитить виновных, но вы поняли идею.

  • Все таблицы InnoDB.
  • Check table возвращается нормально в обеих таблицах.

РЕДАКТИРОВАТЬ: спасибо за предложение использовать LEFT JOIN. Это определенно подтверждает, что проблема заключается в ошибке MySQL.

mysql> SELECT count(s.server_id) FROM server s LEFT JOIN ips i on s.server_id = i.server_id WHERE i.server_id IS NULL;
+--------------------+
| count(s.server_id) |
+--------------------+
|               9277 | 
+--------------------+
1 row in set (0.04 sec)

Начиная с 9277 + 13811 = 23088, это означает, что все серверы без ips + все серверы с ips действительно == все серверы.

Я запланировал обновление сервера mysql на начало следующей недели. Оставайтесь с нами.

Ответы [ 8 ]

7 голосов
/ 10 октября 2009

Какая версия MySQL? Кажется, есть ошибка в <5.0.25 / 5.1.12, которая может быть виновником: </p>

Ошибка # 21282 : NOT IN, более 1000 возвращает неверные результаты с INDEX :

Использование SELECT ... WHERE some_field NOT IN (...), а затем 1000 или более значений в NOT Частично заставляет сервер возвращать неверные результаты, если есть ключ INDEX / UNIQUE строка field. Менее 1000 критериев работает правильно.

6 голосов
/ 10 октября 2009

У вас есть нули в столбцах?

4 голосов
/ 10 октября 2009

server_id not in (ids) не соответствует NULL столбцам, поэтому вы получаете только те серверы с ненулевым server_id, которого нет среди ips. Вместо этого вы захотите использовать where server_id is null.

2 голосов
/ 10 октября 2009

Предполагая, что ошибка найден труппо вызывает это, вы можете использовать этот обходной путь:

select count(*)
from server s
left join ips i on i.server_id = s.server_id
where i.server_id is null

Выше i.server_id is null имеет значение true, если left join не нашел соответствия (точно так же, как все столбцы из i дали бы null для этой ситуации).

1 голос
/ 10 октября 2009

если у вас есть NULL в ваших столбцах, они оценятся как ложные в обоих случаях. результат, который вы получаете: in + not in - nulls

1 голос
/ 10 октября 2009

Есть ли у вас запись с NULL для server_id? Потому что это будет исключено в обоих случаях.

0 голосов
/ 11 октября 2009

Я бы предположил, что с IN и NOT IN происходит что-то странное. Это может быть ошибка или «известное ограничение».

Я бы предложил сначала попытаться ответить на ваш первоначальный вопрос (серверы без IP-адреса), а затем взглянуть на данные ... возможно, это даст вам представление о том, что может происходить.

Итак, вот несколько альтернативных идей, чтобы дать вам то, что вы ищете:

SELECT server_id
FROM server
MINUS
SELECT server_id
FROM ips

Или

SELECT server_id
FROM server s LEFT JOIN ips i on s.server_id = i.server_id
WHERE i.server_id is null

Как сказано выше, это может дать вам представление о том, почему данные не «улавливаются» вашими исходными утверждениями.

0 голосов
/ 10 октября 2009
select count(*) 
from server 
where server_id not in (select distinct(server_id) from ips)
or server_id is NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...