powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Условие Where - у меня уже крыша едет, помогите!
13 сообщений из 13, страница 1 из 1
Условие Where - у меня уже крыша едет, помогите!
    #32032980
Hibernate
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В табличке есть поле Int, которое может иметь значение Null
Нужно выбрать из таблички по условию, которое передается в переменной, которая может быть тоже NULL

Пишу следующий код:
Select *
From tbl_GoodsNames
Where (ParentID = @ParentID) Or (ParentID Is Null And @ParentID Is Null)

Все прекрасно!
Теперь надобно написать условие, чтобы вернулись все записи, которые не попали в первое условие.
Пишу код (все тоже самое, что и перед этим, только ставлю Not на все выражение):
Select *
From tbl_GoodsNames
Where NOT((ParentID = @ParentID) Or (ParentID Is Null And @ParentID Is Null))

Все работает на ура, пока в переменной @ParentID не предадут NULL... - в этом случае первый Select отрабатывает правильно, а второй возвращает пустой набор.

Я уже попинал по-всякому, и сложилось такое впечатление, что скобка (ParentID = @ParentID) в случае @ParentID = NULL всегда возвращает True, хотя этого не дожно быть!!!

Стоит MSSQL2000 Sp2

Помогите, кто может!
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32032981
Hbernate
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ха!
Последнее условие переписал вот так и все заработало!
Код: plaintext
1.
2.
3.
4.
5.
6.
Select * 
From tbl_GoodsNames 
Where 
(NOT(ParentID = @ParentID))
Or 
(NOT(ParentID Is Null And @ParentID Is Null)) 

Народ, чего я не понимаю!?
Ведь условия по сути своей аналогичные!
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32032984
AAron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
привет
собственно ко второму замечанию, насколько я помню всегда было так
Код: plaintext
1.
NOT (a OR b) = NOT(a) AND NOT(b)


насчет (ParentID = @ParentID), в случае @ParentID = NULL, думаю проще проверить взяв
Код: plaintext
1.
select (ParentID = @ParentID)

где @ParentID is NULL
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32032991
gena
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может так?

Код: plaintext
1.
2.
3.
4.
Select * 
From tbl_GoodsNames 
WHERE PK NOT IN (Select PK 
From tbl_GoodsNames 
Where (ParentID = @ParentID) Or (ParentID Is Null And @ParentID Is Null) )
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32032994
Фотография Слон
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все дело тут в том, что сравнение с NULL - это особенная логика. Сравнение любого значения с NULL всегда будет давать NULL. даже NULL c NULL будет NULL, а не true или false. Вернее он будет преобразовываться в false при любой операции.

Я бы переписал выражения таким образом:
Код: plaintext
1.
2.
3.
4.
5.
SELECT * 
FROM tbl_GoodsNames 
WHERE 
     (@ParentID IS NOT NULL AND ParentID = @ParentID)
     OR (@ParentID IS NULL AND ParentID IS NULL) 

а второе как:
Код: plaintext
1.
2.
3.
4.
5.
SELECT * 
FROM tbl_GoodsNames 
WHERE 
     (@ParentID IS NOT NULL AND ParentID <> @ParentID)
     OR (@ParentID IS NULL AND ParentID IS NOT NULL) 


-- Слон
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32032995
Фотография Слон
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу прощение. Второе надо было переписывать так:
Код: plaintext
1.
2.
3.
4.
5.
SELECT * 
FROM tbl_GoodsNames 
WHERE 
     (@ParentID IS NOT NULL AND (ParentID <> @ParentID OR ParentID IS NULL))
     OR (@ParentID IS NULL AND ParentID IS NOT NULL) 


-- Слон
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32032998
Dominic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я поступаю в таких случаях примерно так:

IF @ParentID IS NULL
SELECT * FROM table1 WHERE ParentID IS NULL
ELSE
SELECT * FROM table1 WHERE ParentID = @ParentID

Если не проще, то по крайней мере наглядно.
Если такое ветвление не подходит, пробуй функцию ISNULL, подменяющее значение своего аргумента, имеющего значение NULL, на некоторую, устраивающую разработчика величину - например, на 0:

SELECT *
FROM table1
WHERE ISNULL(ParentID,0) = ISNULL(@ParentID,0)

Что-то я посмотрел следующие за первым постинги и не совсем понял, какую задачу тебе решить-то требуется? Попытаюсь проговорить, что я увидел:
"Найти записи, соответствующие заданному значению, при этом значение NULL рассматривается как самостоятельное значение". - это по первому постингу, на его я и ответил примером.
А вот по второму... "Найти записи, несовпадающие с заданным значением, либо одновременно с заданным значением имеющих значение NULL". Что ж, модифицируем мой пример (условие WHERE в ветке ELSE):

IF @ParentID IS NULL
SELECT * FROM table1 WHERE ParentID IS NULL
ELSE
SELECT * FROM table1 WHERE ParentID != @ParentID
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32033000
Фотография Слон
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблема с ISNULL в WHERE clause только лишь та, что при этом SQL server будет преобразовывать все значения в указанном столбце, а потом уже сравнивать. В том числе это не позволяет использование индекса на полную катушку.

Что касается примера второго запроса (SELECT * FROM table1 WHERE ParentID != @ParentID), то опять же из-за того, что логика сравнения с NULL была попросту игнорирована, то результат вернет все значения, кроме тех, где ParentID IS NULL, опять же потому, что при любом сравнении значения NULL из столбца ParentID с NOT NULL значением @ParentID в результате будет NULL (aka UNKNOWN), которое будет преобразовано в данном случае в FALSE


-- Слон
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32033036
Hbernate
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сравнение любого значения с NULL всегда будет давать NULL. даже NULL c NULL будет NULL, а не true или false. Вернее он будет преобразовываться в false при любой операции.

Именно этим правилом я и пользовался, когда писал:
Код: plaintext
Where NOT((ParentID = @ParentID) Or (ParentID Is Null And @ParentID Is Null)) 

если разобрать по-косточкам, то первая скобка при @ParentID = NULL всегда дает False, вторая дает True только если ParentID Is Null. Отсюда следует, что должны выбраться все записи, у которых @ParentID <> NULL, что мне и надо было. Но данное условие вообще никогда не возвращает ни одной записи!!! Что меня и смущает. Конечно, вот так все работает(Спасибо Слону):
Код: plaintext
1.
2.
3.
WHERE 
     (@ParentID IS NOT NULL AND (ParentID <> @ParentID OR ParentID IS NULL))
     OR (@ParentID IS NULL AND ParentID IS NOT NULL) 

я в конце концов и сам пришел к этому, но это метод тыка, который меня уже давно не устраивает. Я так и не понял ПОЧЕМУ изначальный вариант не работает :-((

Что-то я посмотрел следующие за первым постинги и не совсем понял, какую задачу тебе решить-то требуется?

мне нужно сформировать два набора, сформированных по определенному условию из исходного набора, эти два набора должны взаимно дополнять друг друга, тоесть в сумме они должны составить исходный набор.
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32033038
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Именно этим правилом я и пользовался, когда писал:

>Where NOT((ParentID = @ParentID) Or (ParentID Is Null And @ParentID Is Null))

>если разобрать по-косточкам, то первая скобка при @ParentID = NULL всегда дает False

Первое выражение при @ParentID равное NULL будет не false, а NULL. Соответственно NULL Or (ParentID Is Null And @ParentID Is Null) тоже будет NULL.

С помощью SET ANSI_NULLS ON OFF можно включить вычисление NULL-ов при операциях сравнения как false. Тогда ваш первоначальный запрос будет работать правильно
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32033041
Dominic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С "постановкой задачи" все стало ясно. Хорошо, что найден вариант, устраивающий разработчика. Насчет "ПОЧЕМУ изначальный вариант не работает" - да потому, что если хотя бы одно значение в выражении обращается в NULL, все выражение без дополнительного анализа обращается в NULL, а не какая-то его часть в false.
И все же я бы порекомендовал вариант с IF...ELSE как наглядный (отдельно обрабатывается ситуация, когда @ParentID NULL, и когда нет). Представьте, что с этим будет разбираться кто-то другой.

С уважением, Dominic
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32033088
Hibernate
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Первое выражение при @ParentID равное NULL будет не false, а NULL. Соответственно NULL Or (ParentID Is Null And @ParentID Is Null) тоже будет NULL.

и соответственно Not NULL дает тоже NULL.... и все сыплется мелким прахом...

Ну теперечи вроде уяснил!
Спасибо всем!!!

И все же я бы порекомендовал вариант с IF...ELSE как наглядный (отдельно обрабатывается ситуация, когда @ParentID NULL, и когда нет). Представьте, что с этим будет разбираться кто-то другой.

совет дельный, спасибо, но в данном случае хотелось докопаться до того что-же я все-таки не понимаю.
...
Рейтинг: 0 / 0
Условие Where - у меня уже крыша едет, помогите!
    #32033587
tmpnick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>Первое выражение при @ParentID равное NULL будет не >false, а NULL. Соответственно NULL Or (ParentID Is Null And >@ParentID Is Null) тоже будет NULL.

Не всегда. Если ParentID is null, то вторая скобка TRUE. А
NULL OR TRUE, как известно, равно TRUE...
(А NULL AND FALSE = FALSE)

Вообще, имхо, стоит посмотреть таблицу значений фунций в трехзначной логике и все станет ясно..
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Условие Where - у меня уже крыша едет, помогите!
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]