Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 select ... where ... in () + select ... where ... not in () <> select ...  [new]
Полина
Member

Откуда: Петербург
Сообщений: 205
Столкнулась впервые
Tab1.ROUTE_NO - int, allow null
AllRoutes.RouteNo - varchar(8)

select count(*) from Tab1 where ROUTE_NO not in (select CAST(RouteNo as int) from AllRoutes)
select count(*) from Tab1 where ROUTE_NO in (select CAST(RouteNo as int) from AllRoutes)

Получаю соответственно 30214 и 0

по идее ожидаю, что сумма должна быть полным кол-вом записей таблицы Tab1
Ан нет...
select count(*) from Tab1 

- в таблице записей 30622

Поделитесь мыслями, думаю что проблема не в запросе а в настройке SQL?
23 май 14, 10:48    [16059823]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
Glory
Member

Откуда:
Сообщений: 104751
Полина
Tab1.ROUTE_NO - int, allow null

любое сравение с NULL есть "неопределено"

Полина
Поделитесь мыслями, думаю что проблема не в запросе а в настройке SQL?

Проблема в незнании троичной логики с участием NULL-ов
23 май 14, 10:50    [16059839]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
invm
Member

Откуда: Москва
Сообщений: 9845
Полина
Tab1.ROUTE_NO - int, allow null
null not in (...) есть unknown, а не true. Поэтому и получаете такой результат.
23 май 14, 10:52    [16059856]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Что вернёт
select count(*) from Tab1 where ROUTE_NO IS NULL
?

Совет: никогда не применяйте NOT IN(SELECT ...)
Заменяйте на NOT EXISTS(SELECT * FROM ... WHERE ...)
23 май 14, 10:53    [16059867]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
Полина
Member

Откуда: Петербург
Сообщений: 205
iap, спасибо за совет.
Точно, проблема из-за null

Спасибо всем!
23 май 14, 10:55    [16059877]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
Полина
Member

Откуда: Петербург
Сообщений: 205
iap

Совет: никогда не применяйте NOT IN(SELECT ...)
Заменяйте на NOT EXISTS(SELECT * FROM ... WHERE ...)

попробовала заменить - ошибка
Incorrect syntax near the keyword 'EXISTS'.
23 май 14, 10:58    [16059902]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
Полина
Member

Откуда: Петербург
Сообщений: 205
я обычно использую
if not exists ()
begin
...
end

но просто выбор данных
select... from ... where a not in ()
23 май 14, 11:00    [16059925]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Полина
iap
Совет: никогда не применяйте NOT IN(SELECT ...)
Заменяйте на NOT EXISTS(SELECT * FROM ... WHERE ...)

попробовала заменить - ошибка
Incorrect syntax near the keyword 'EXISTS'.
select count(*) from Tab1 T where not exists (select * from AllRoutes R WHERE CAST(R.RouteNo as int)=T.ROUTE_NO)
Забыл спросить, а в чём тайный смысл в конвертировании RouteNo в INT?
Если по RouteNo есть индекс, то Вы мешаете серверу его использовать.
23 май 14, 11:02    [16059941]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Полина,

как по-Вашему, что вернёт запрос
WITH
 CTE1 AS(SELECT * FROM(VALUES(0),(1),(20),(NULL))T(V))
,CTE2 AS(SELECT * FROM(VALUES(0),(2),(3))T(V))
SELECT * FROM CTE2 WHERE V NOT IN(SELECT V FROM CTE1);
?

А этот:
WITH
 CTE1 AS(SELECT * FROM(VALUES(0),(1),(20),(NULL))T(V))
,CTE2 AS(SELECT * FROM(VALUES(0),(2),(3))T(V))
SELECT * FROM CTE2 WHERE NOT EXISTS(SELECT * FROM CTE1 WHERE CTE1.V=CTE2.V);
?

А всё из-за единственного NULL в CTE1
23 май 14, 11:09    [16059999]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
Полина
Member

Откуда: Петербург
Сообщений: 205
[quot iap]
Полина
пропущено...

Забыл спросить, а в чём тайный смысл в конвертировании RouteNo в INT?
Если по RouteNo есть индекс, то Вы мешаете серверу его использовать.


Смысла нет. Такая база в наследство досталась:(
23 май 14, 11:11    [16060026]     Ответить | Цитировать Сообщить модератору
 Re: select ... where ... in () + select ... where ... not in () <> select ...  [new]
Полина
Member

Откуда: Петербург
Сообщений: 205
iap
Полина,

как по-Вашему, что вернёт запрос
WITH
 CTE1 AS(SELECT * FROM(VALUES(0),(1),(20),(NULL))T(V))
,CTE2 AS(SELECT * FROM(VALUES(0),(2),(3))T(V))
SELECT * FROM CTE2 WHERE V NOT IN(SELECT V FROM CTE1);
?

А этот:
WITH
 CTE1 AS(SELECT * FROM(VALUES(0),(1),(20),(NULL))T(V))
,CTE2 AS(SELECT * FROM(VALUES(0),(2),(3))T(V))
SELECT * FROM CTE2 WHERE NOT EXISTS(SELECT * FROM CTE1 WHERE CTE1.V=CTE2.V);
?

А всё из-за единственного NULL в CTE1


Солидно... Я как-то всегда NOT IN использовала...
Спасибо за науку!
23 май 14, 11:17    [16060064]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить