Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > case/when oracle неверная выборка


Автор: ayscha 26.3.2011, 12:53
Добрый день.
Составляю запрос под оракл типа case/when и получаю не то, что надо.

Вот запрос.

SELECT 
    CASE 
      WHEN (p.fk_id is null AND p.name is not null) THEN p.name       /* тут выполняется неверно*/
       /* ELSE c.name*/
    END
    AS name
FROM some_schema.c_table c
INNER JOIN some_schema.p_table p
ON p.fk_id = c.id;

Ожидаю получить p.name в случае, если внешний ключ нулевой ( но при этом не нулевое p.name), иначе с.name

На самом деле получаю:

NAME
null
null
null
...

Т.е выбираются как раз нулевые значения. Вообще непонятно откуда такой результат. 
case/when вообще умеет работать со строками??

Заранее спасибо за ответы.

Автор: Zloxa 26.3.2011, 18:00
Цитата(ayscha @  26.3.2011,  12:53 Найти цитируемый пост)
Т.е выбираются как раз нулевые значения

Если ни один when кейса не вернул истину, и отсутствует кляуза else, результат выражения - null.

Добавлено через 1 минуту и 15 секунд
Цитата

 If none of the WHEN ... THEN pairs meet this condition, and an ELSE clause exists, then Oracle returns else_expr. Otherwise, Oracle returns null. 

http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/expressions004.htm#sthref2637

Добавлено через 12 минут и 2 секунды
Цитата(ayscha @  26.3.2011,  12:53 Найти цитируемый пост)
p.fk_id is null

в вашем запросе это выражение ВСЕГДА будет возвращать ложь. В силу того, что по p.fk_id происходит внутреннее соединение, в результат выборки не войдут те строки, значение fk_id для которых не определено 

Автор: ayscha 26.3.2011, 19:58
Цитата(Zloxa @  26.3.2011,  18:00 Найти цитируемый пост)
в вашем запросе это выражение ВСЕГДА будет возвращать ложь. В силу того, что по p.fk_id происходит внутреннее соединение, в результат выборки не войдут те строки, значение fk_id для которых не определено


А что это значит внутреннее соединение?
Дело в том, что в таблице p fk_id во многих строках как раз null.

к тому же, если я делаю обычный select и join'ом с условием p.fk_id is null мне выдаются нужные строки.


Автор: Zloxa 26.3.2011, 23:27
Цитата(ayscha @  26.3.2011,  19:58 Найти цитируемый пост)
А что это значит внутреннее соединение?

inner join
Цитата(ayscha @  26.3.2011,  19:58 Найти цитируемый пост)
к тому же, если я делаю обычный select и join'ом с условием p.fk_id is null мне выдаются нужные строки.

к чему же?
Если вы меняете критерий соединения, это ведь совсем уже другой запрос получается, так ведь?

Автор: ayscha 29.3.2011, 17:21
Цитата(Zloxa @  26.3.2011,  23:27 Найти цитируемый пост)
к чему же?
Если вы меняете критерий соединения, это ведь совсем уже другой запрос получается, так ведь?


Простите, долго не отвечала.
Так вот. я, наверное, что-то очень сильно не понимаю, но разве следующие два запроса не должны делать одно и тоже?
Код


SELECT P.NAME as name
  FROM P_TABLE P
  WHERE P.FK_CDO_TABLE IS NULL
UNION
SELECT cdo.name as name
  FROM P_CDO_TABLE CDO
  INNER JOIN P_TABLE P
  ON CDO.ID = P.FK_CDO_TABLE
  WHERE P.FK_CDO_TABLE IS NOT NULL;



SELECT 
    CASE 
      WHEN P.FK_CDO_TABLE is not null THEN P.NAME
      ELSE CDO.NAME
    END
    AS NAME
FROM P_CDO_DESTINATION CDO
INNER JOIN P_TABLE P
ON P.FK_CDO_TABLE = CDO.ID;





Автор: Zloxa 29.3.2011, 17:27
ayscha, тот факт, что второй запрос не возвращает ожидаемый вами результат, для Вас не показателен?
Думаете оракл глючит?

Автор: ayscha 31.3.2011, 11:27
Цитата(Zloxa @  29.3.2011,  17:27 Найти цитируемый пост)
ayscha, тот факт, что второй запрос не возвращает ожидаемый вами результат, для Вас не показателен?
Думаете оракл глючит? 


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

Заранее спасибо за разъяснения.

Автор: Zloxa 31.3.2011, 14:08
Цитата(ayscha @  31.3.2011,  11:27 Найти цитируемый пост)
Я поэтому и обращаюсь на форум с надеждой что кото-нибудь сможет мне показать на ошибку,

Если запрос смог быть выполнен, он не содержит ошибки.

Автор: ayscha 31.3.2011, 14:28
Цитата(Zloxa @  31.3.2011,  14:08 Найти цитируемый пост)
Если запрос смог быть выполнен, он не содержит ошибки.


Уважаемый Zloxa, Вы прекрасно понимаете что конкретно спрашивается в вопросе. Поэтому, если у Вас нет ответов по делу, прошу вообще не писать.

Я зашла на форум в раздел, в котором в основном постятся новички. Если Вас раздражают подобного рода вопросы, то можно просто на них не отвечать либо посещать более профессиональные форумы.

Автор: Zloxa 31.3.2011, 15:01
Цитата(ayscha @  31.3.2011,  14:28 Найти цитируемый пост)
 Вы прекрасно понимаете что конкретно спрашивается в вопросе

именно что - нет. 
Мне казалось что я дал вам разъяснение от чего вы получаете тот результат, который получаете, однако я не понял поняли ли Вы его или не поняли, судя по отсутствию уточняющих вопросов - поняли.
Мне казалось что я однозначно указал на очевидность того, что приведенные вами запросы - не эквивалентны.

Мне действително не понятно какие еще у вас вопросы остались.

Автор: ayscha 31.3.2011, 15:45

Хорошо, тогда давайте вернемся к первым комментариям. smile

Получается, что when/case не подходит для случаев, когда в качесте аргумента указывается внешний ключ?

Я сделала свою задачи в итоге с помощью юнионов, но мне кажется, что данный запрос очень громоздкий и неизящный.
есть ли какой-нибудь способ сделать все тоже самое, только более изящным способ.
исходная задача была выбрать имя из первой таблицы в случае, если внешний ключ на вторую таблицу нулевой,
иначе выбирать по внешнему ключу соответствующее поле из второй таблицы

Автор: Zloxa 31.3.2011, 15:58
Цитата(ayscha @  31.3.2011,  15:45 Найти цитируемый пост)
 выбрать имя из первой таблицы в случае, если внешний ключ на вторую таблицу нулевой,
иначе выбирать по внешнему ключу соответствующее поле из второй таблицы 

уже хоть что-то, но все равно можно интерпретировать не однозначно.
Полагаю вам нужно что-то вроде:
Код

SELECT 
    nvl(p.name,c.name) AS name
FROM some_schema.c_table c
left JOIN some_schema.p_table p
ON p.fk_id = c.id;


/*однако ж этот запрос таки не эквивалентен запросу с юнион.*/

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)