Как я могу сделать предложение NOT IN NULL-безопасным? - PullRequest
0 голосов
/ 07 мая 2018

Вот моя структура таблицы:

// questions_and_answers
+----+-------------------+------+----------+
| id |       body        | type | related  |
+----+-------------------+------+----------+
| 1  | a question        | 0    | NULL     |
| 2  | my answer         | 1    | 1        |
| 3  | another answer    | 1    | 1        |
| 4  | another question  | 0    | NULL     |
| 5  | another answer    | 1    | 4        |
| 6  | another answer    | 1    | 1        |  
+----+-------------------+------+----------+
-- type column: it is either 0 for questions and 1 for answers.
-- related column: it is either null for questions and "the id of its question" for answers

Теперь мне нужно выбрать все неотвеченные вопросы. Вот мой запрос:

SELECT *
FROM questions_and_answers AS qa
WHERE
  type = 0 -- just questions
  AND
  qa.id NOT IN (SELECT q.related FROM qanda q WHERE q.type <> 0) -- unanswered ones

Работает хорошо и все нормально.


Какой у меня вопрос? Мой запрос не соответствует ни одной строке, если есть такая строка:

| 7  | another answer    | 1    | NULL      |

См? значение type равно 1, так что это ответ. Но значение related равно NULL, поэтому оно не указывает ни на один вопрос. В общем, эта строка не имеет смысла, но, вероятно, иногда случается (когда вопрос удаляется, и мы устанавливаем related его ответов на null). В этом случае результатом моего запроса будет "строка не выбрана" .

Почему? И как я могу защитить свой запрос от такой ситуации? (безопасно == игнорировать их и сопоставлять оставшиеся без ответа вопросы)

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Вы должны удалить только все эти записи (related = NULL) из второго SELECT, как это

SELECT *
FROM qa
WHERE type = 0 -- just questions
  AND id NOT IN 
    (SELECT related 
       FROM qa
       WHERE type <> 0
         AND related IS NOT NULL
    )
0 голосов
/ 07 мая 2018

Использование not exists:

where not exists (select 1 from quanda q where q.related = qa.id and q.type <> 0)

Я настоятельно рекомендую никогда не использовать not in с подзапросом, особенно из-за проблемы NULL. Просто используйте not exists. Оптимизировать также легче с помощью индекса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...